mirror of
https://github.com/reaaLx/nx1-gsc-dump.git
synced 2025-06-27 14:51:54 +00:00
Incomplete SP dump provided by Louvenarde
This commit is contained in:
126
animscripts/animmode.gsc
Normal file
126
animscripts/animmode.gsc
Normal file
@ -0,0 +1,126 @@
|
||||
main()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "stop_animmode" );
|
||||
self notify( "killanimscript" );
|
||||
self._tag_entity endon( self._anime );
|
||||
|
||||
if ( isdefined( self._custom_anim_thread ) )
|
||||
{
|
||||
self thread [[ self._custom_anim_thread ]]();
|
||||
self._custom_anim_thread = undefined;
|
||||
}
|
||||
|
||||
loop = isdefined( self._custom_anim_loop ) && self._custom_anim_loop;
|
||||
if ( loop )
|
||||
{
|
||||
self endon( "stop_loop" );
|
||||
self._custom_anim_loop = undefined;
|
||||
}
|
||||
else
|
||||
{
|
||||
thread notify_on_end( self._anime );
|
||||
}
|
||||
|
||||
anime = self._anime;
|
||||
self._anime = undefined;
|
||||
|
||||
arraySize = 0;
|
||||
if ( loop )
|
||||
{
|
||||
arraySize = level._scr_anim[ self._animname ][ anime ].size;
|
||||
animationName = level._scr_anim[ self._animname ][ anime ][ randomint( arraySize ) ];
|
||||
}
|
||||
else
|
||||
{
|
||||
animationName = level._scr_anim[ self._animname ][ anime ];
|
||||
}
|
||||
|
||||
origin = getstartOrigin( self._tag_entity.origin, self._tag_entity.angles, animationName );
|
||||
angles = getstartAngles( self._tag_entity.origin, self._tag_entity.angles, animationName );
|
||||
|
||||
newOrigin = self getDropToFloorPosition( origin );
|
||||
if ( isdefined( newOrigin ) )
|
||||
origin = newOrigin;
|
||||
else
|
||||
println( "Custom animation may be playing in solid for entity '" + self getentnum() + "'\n" );
|
||||
|
||||
if ( !isdefined( self.noTeleport ) )
|
||||
self teleport( origin, angles );
|
||||
|
||||
self.pushable = 0;
|
||||
|
||||
clear_time = 0.3;
|
||||
blend_time = 0.2;
|
||||
|
||||
if ( isdefined( self.anim_blend_time_override ) )
|
||||
{
|
||||
clear_time = self.anim_blend_time_override;
|
||||
blend_time = self.anim_blend_time_override;
|
||||
}
|
||||
|
||||
self animMode( self._animmode );
|
||||
self clearAnim( self.root_anim, clear_time );
|
||||
|
||||
// self setAnim( %body, 1, 0 ); // The %body node should always have weight 1.
|
||||
self OrientMode( "face angle", angles[ 1 ] );
|
||||
|
||||
anim_string = "custom_animmode";
|
||||
self setflaggedanimrestart( anim_string, animationName, 1, blend_time, 1 );
|
||||
self._tag_entity thread maps\_anim::start_notetrack_wait( self, anim_string, anime, self._animname );
|
||||
self._tag_entity thread maps\_anim::animscriptDoNoteTracksThread( self, anim_string, anime );
|
||||
|
||||
//thread maps\_debug::drawArrowForever( self._tag_entity.origin, self._tag_entity.angles );
|
||||
|
||||
tag_entity = self._tag_entity;
|
||||
self._tag_entity = undefined;
|
||||
self._animmode = undefined;
|
||||
|
||||
self endon( "killanimscript" );
|
||||
|
||||
endMarker = "end";
|
||||
|
||||
if ( !loop )
|
||||
{
|
||||
if ( animHasNoteTrack( animationName, "finish" ) )
|
||||
endMarker = "finish";
|
||||
else if ( animHasNoteTrack( animationName, "stop anim" ) )
|
||||
endMarker = "stop anim";
|
||||
}
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittillmatch( anim_string, endMarker );
|
||||
|
||||
if ( loop )
|
||||
{
|
||||
animationName = level._scr_anim[ self._animname ][ anime ][ randomint( arraySize ) ];
|
||||
self SetFlaggedAnimKnobLimitedRestart( anim_string, animationName, 1, 0.2, 1 );
|
||||
|
||||
if ( isdefined( tag_entity ) )
|
||||
{
|
||||
tag_entity thread maps\_anim::start_notetrack_wait( self, anim_string, anime, self._animname );
|
||||
tag_entity thread maps\_anim::animscriptDoNoteTracksThread( self, anim_string, anime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( endMarker != "end" )
|
||||
self OrientMode( "face motion" );
|
||||
|
||||
self notify( "finished_custom_animmode" + anime );
|
||||
}
|
||||
|
||||
notify_on_end( msg )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "finished_custom_animmode" + msg );
|
||||
|
||||
self waittill( "killanimscript" );
|
||||
|
||||
self notify( "finished_custom_animmode" + msg );
|
||||
}
|
1524
animscripts/animset.gsc
Normal file
1524
animscripts/animset.gsc
Normal file
File diff suppressed because it is too large
Load Diff
4630
animscripts/battlechatter.gsc
Normal file
4630
animscripts/battlechatter.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1544
animscripts/battlechatter_ai.gsc
Normal file
1544
animscripts/battlechatter_ai.gsc
Normal file
File diff suppressed because it is too large
Load Diff
58
animscripts/civilian.gsc
Normal file
58
animscripts/civilian.gsc
Normal file
@ -0,0 +1,58 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
cover()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
|
||||
if ( self animscripts\utility::IsInCombat() )
|
||||
situation = "idle_combat";
|
||||
else
|
||||
situation = "idle_noncombat";
|
||||
|
||||
idle_array = undefined;
|
||||
if ( isdefined( self.animname ) && isdefined( level._scr_anim[ self.animname ] ) )
|
||||
idle_array = level._scr_anim[ self.animname ][ situation ];
|
||||
|
||||
if ( !isdefined( idle_array ) )
|
||||
{
|
||||
if ( !isdefined( level._scr_anim[ "default_civilian" ] ) )
|
||||
return;
|
||||
|
||||
idle_array = level._scr_anim[ "default_civilian" ][ situation ];
|
||||
}
|
||||
|
||||
thread move_check();
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self setflaggedanimknoball( "idle", random( idle_array ), %root, 1, 0.2, 1 );
|
||||
self waittillmatch( "idle", "end" );
|
||||
}
|
||||
}
|
||||
|
||||
move_check()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
while ( !isdefined( self.champion ) )
|
||||
{
|
||||
wait( 1 );
|
||||
}
|
||||
}
|
||||
|
||||
stop()
|
||||
{
|
||||
cover();
|
||||
}
|
||||
|
||||
get_flashed_anim()
|
||||
{
|
||||
return anim.civilianFlashedArray[ randomint( anim.civilianFlashedArray.size ) ];
|
||||
}
|
19
animscripts/civilian/civilian_flashed.gsc
Normal file
19
animscripts/civilian/civilian_flashed.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
|
||||
|
||||
get_flashed_anim()
|
||||
{
|
||||
return anim.civilianFlashedArray[ randomint( anim.civilianFlashedArray.size ) ];
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
flashDuration = self flashBangGetTimeLeftSec();
|
||||
if ( flashDuration <= 0 )
|
||||
return;
|
||||
|
||||
animscripts\flashed::flashBangedLoop( get_flashed_anim(), flashDuration );
|
||||
}
|
74
animscripts/civilian/civilian_init.gsc
Normal file
74
animscripts/civilian/civilian_init.gsc
Normal file
@ -0,0 +1,74 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
animscripts\init::main();
|
||||
|
||||
if ( !isdefined( level._initialized_civilian_animations ) )
|
||||
{
|
||||
initCivilianAnims();
|
||||
}
|
||||
|
||||
animscripts\civilian\civilian_init_common::civilian_init();
|
||||
}
|
||||
|
||||
initCivilianAnims()
|
||||
{
|
||||
level._initialized_civilian_animations = true;
|
||||
|
||||
|
||||
//put the default ones here:
|
||||
level._scr_anim[ "default_civilian" ][ "run_combat" ] = [ %civilian_run_upright ];
|
||||
level._scr_anim[ "default_civilian" ][ "run_hunched_combat" ] = [ %civilian_run_hunched_A, %civilian_run_hunched_C, %civilian_run_hunched_flinch ];
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_noncombat" ] = [ %civilian_walk_cool ];
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_hunched_weights" ] = get_cumulative_weights( [3, 3, 1] );
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_weights" ] = get_cumulative_weights( [ 1 ] );
|
||||
level._scr_anim[ "default_civilian" ][ "idle_noncombat" ] = [ %unarmed_cowerstand_idle ];
|
||||
level._scr_anim[ "default_civilian" ][ "idle_combat" ] = [ %casual_crouch_v2_idle, %unarmed_cowercrouch_idle_duck ];
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "dodge_left" ] = %civilian_briefcase_walk_dodge_L;
|
||||
level._scr_anim[ "default_civilian" ][ "dodge_right" ] = %civilian_briefcase_walk_dodge_R;
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "react_stumble" ] = [ %run_react_stumble ];
|
||||
|
||||
//7 9 <- 8 is invalid, it's straight.
|
||||
//4 6 <- 5 is invalid, it's not a turn.
|
||||
//1 2 3
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][1] = %civilian_run_upright_turnL135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][2] = %civilian_run_upright_turn180;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][3] = %civilian_run_upright_turnR135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][4] = %civilian_run_upright_turnL90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][6] = %civilian_run_upright_turnR90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][7] = %civilian_run_upright_turnL45;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][9] = %civilian_run_upright_turnR45;
|
||||
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][1] = %civilian_run_upright_turnL135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][2] = %civilian_run_upright_turn180;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][3] = %civilian_run_upright_turnR135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][4] = %civilian_run_hunched_turnL90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][6] = %civilian_run_hunched_turnR90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][7] = %civilian_run_hunched_turnL45;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][9] = %civilian_run_hunched_turnR45;
|
||||
|
||||
//a more dramatic version. Randomly chosen from.
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][1] = [];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][2] = [];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][3] = [];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][4] = [ %civilian_run_hunched_turnL90_slide, %civilian_run_hunched_turnL90_stumble ];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][6] = [ %civilian_run_hunched_turnR90_slide, %civilian_run_hunched_turnR90_stumble ];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][7] = [];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][9] = [];
|
||||
|
||||
//TagCC<NOTE>: not happy with this, but we don't have flashes around civilians on the moon,
|
||||
//so I'm hesistent to mess with this just yet.
|
||||
anim.civilianFlashedArray = [ %unarmed_cowerstand_react, %unarmed_cowercrouch_react_A, %unarmed_cowercrouch_react_B ];
|
||||
}
|
229
animscripts/civilian/civilian_init_common.gsc
Normal file
229
animscripts/civilian/civilian_init_common.gsc
Normal file
@ -0,0 +1,229 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
civilian_init()
|
||||
{
|
||||
self.allowdeath = 1;
|
||||
self.disablearrivals = true;
|
||||
self.disableexits = true;
|
||||
self.neverEnableCQB = true;
|
||||
self.alwaysRunForward = true;
|
||||
self OrientMode( "face default" );
|
||||
self.combatmode = "no_cover";
|
||||
self.pushplayer = false;
|
||||
self pushplayer( false );
|
||||
self.a.reactToBulletChance = 1;
|
||||
|
||||
|
||||
|
||||
// set the civilians animname to use defaults, or specific group if specified in radiant
|
||||
animName = undefined;
|
||||
if ( isdefined( self.civilian_walk_animation ) )
|
||||
{
|
||||
self.animname = self.civilian_walk_animation;
|
||||
self attachProps( self.civilian_walk_animation );
|
||||
self.alertLevel = "noncombat";
|
||||
startNonCombat();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.animname = "default_civilian";
|
||||
self.alertLevel = "alert";
|
||||
startCombat();
|
||||
}
|
||||
|
||||
self thread checkCombatState();
|
||||
|
||||
// Make sure all required anims exist for this civilian, or set some defaults if they weren't specified
|
||||
assert( isdefined( level._scr_anim[ self.animname ][ "run_noncombat" ] ) );
|
||||
|
||||
self.dropWeapon = false;
|
||||
self DropAIWeapon();
|
||||
self.saved = false;
|
||||
}
|
||||
|
||||
attachProps( anime )
|
||||
{
|
||||
if ( isdefined( self.hasAttachedProps ) )
|
||||
return;
|
||||
|
||||
initCivilianProps();
|
||||
|
||||
prop_model = anim.civilianProps[ anime ];
|
||||
|
||||
if ( isdefined( prop_model ) )
|
||||
{
|
||||
self attach( prop_model, "tag_inhand", true );
|
||||
self.hasAttachedProps = true;
|
||||
}
|
||||
}
|
||||
|
||||
detachProps( anime )
|
||||
{
|
||||
if ( isdefined( self.hasAttachedProps ) )
|
||||
{
|
||||
self.hasAttachedProps = undefined;
|
||||
self detach( anim.civilianProps[ anime ], "tag_inhand" );
|
||||
}
|
||||
}
|
||||
|
||||
initCivilianProps()
|
||||
{
|
||||
if ( isdefined( anim.civilianProps ) )
|
||||
return;
|
||||
|
||||
anim.civilianProps = [];
|
||||
anim.civilianProps[ "civilian_briefcase_walk" ] = "com_metal_briefcase";
|
||||
anim.civilianProps[ "civilian_crazy_walk" ] = "electronics_pda";
|
||||
anim.civilianProps[ "civilian_cellphone_walk" ] = "com_cellphone_on";
|
||||
anim.civilianProps[ "sit_lunch_A" ] = "com_cellphone_on";
|
||||
anim.civilianProps[ "civilian_soda_walk" ] = "ma_cup_single_closed";
|
||||
anim.civilianProps[ "civilian_paper_walk" ] = "paper_memo";
|
||||
anim.civilianProps[ "civilian_coffee_walk" ] = "cs_coffeemug02";
|
||||
anim.civilianProps[ "civilian_pda_walk" ] = "electronics_pda";
|
||||
anim.civilianProps[ "reading1" ] = "open_book";
|
||||
anim.civilianProps[ "reading2" ] = "open_book";
|
||||
anim.civilianProps[ "texting_stand" ] = "electronics_pda";
|
||||
anim.civilianProps[ "texting_sit" ] = "electronics_pda";
|
||||
anim.civilianProps[ "smoking1" ] = "prop_cigarette";
|
||||
anim.civilianProps[ "smoking2" ] = "prop_cigarette";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
startNonCombat()
|
||||
{
|
||||
self.turnRate = 0.2;
|
||||
|
||||
// dodge animations
|
||||
if ( isdefined( self.civilian_walk_animation ) )
|
||||
{
|
||||
dodgeLeft = level._scr_anim[ "default_civilian" ][ "dodge_left" ];
|
||||
dodgeRight = level._scr_anim[ "default_civilian" ][ "dodge_right" ];
|
||||
|
||||
if ( isdefined( level._scr_anim[ self.animname ][ "dodge_left" ] ) )
|
||||
dodgeLeft = level._scr_anim[ self.animname ][ "dodge_left" ];
|
||||
|
||||
if ( isdefined( level._scr_anim[ self.animname ][ "dodge_right" ] ) )
|
||||
dodgeRight = level._scr_anim[ self.animname ][ "dodge_right" ];
|
||||
|
||||
self animscripts\move::setDodgeAnims( dodgeLeft, dodgeRight );
|
||||
}
|
||||
|
||||
// move turn animations
|
||||
if ( isdefined( level._scr_anim[ self.animname ][ "turn_left_90" ] ) )
|
||||
{
|
||||
assert( isdefined( level._scr_anim[ self.animname ][ "turn_right_90" ] ) );
|
||||
self.pathTurnAnimOverrideFunc = animscripts\civilian\civilian_move::civilian_nonCombatMoveTurn;
|
||||
self.pathTurnAnimBlendTime = 0.1;
|
||||
self enable_turnAnims();
|
||||
}
|
||||
else
|
||||
{
|
||||
self disable_turnAnims();
|
||||
}
|
||||
|
||||
self.run_overrideanim = level._scr_anim[ self.animname ][ "run_noncombat" ];
|
||||
self.walk_overrideanim = self.run_overrideanim;
|
||||
|
||||
self.run_overrideBulletReact = undefined;
|
||||
|
||||
if ( self.animname == "default_civilian" )
|
||||
{
|
||||
self.run_override_weights = level._scr_anim[ self.animname ][ "run_weights_noncombat" ];
|
||||
self.walk_override_weights = self.run_override_weights;
|
||||
}
|
||||
}
|
||||
|
||||
startCombat()
|
||||
{
|
||||
self notify( "combat" );
|
||||
|
||||
self animscripts\move::clearDodgeAnims();
|
||||
|
||||
self.pathTurnAnimBlendTime = undefined;
|
||||
self enable_turnAnims();
|
||||
|
||||
self.turnRate = 0.3;
|
||||
|
||||
standing_run = randomint( 3 ) < 1;
|
||||
if ( isdefined( self.force_civilian_stand_run ) )
|
||||
{
|
||||
standing_run = true;
|
||||
}
|
||||
else
|
||||
if ( isdefined( self.force_civilian_hunched_run ) )
|
||||
{
|
||||
standing_run = false;
|
||||
}
|
||||
|
||||
if ( standing_run )
|
||||
{
|
||||
self.pathTurnAnimOverrideFunc = animscripts\civilian\civilian_move::civilian_combatMoveTurn;
|
||||
|
||||
self.run_overrideanim = level._scr_anim[ "default_civilian" ][ "run_combat" ];
|
||||
self.run_override_weights = level._scr_anim[ "default_civilian" ][ "run_weights" ];
|
||||
|
||||
//now check if this animset defines it's own anims
|
||||
if ( IsDefined( level._scr_anim[ self.animname ][ "run_combat" ] ) )
|
||||
{
|
||||
self.run_overrideanim = level._scr_anim[ self.animname ][ "run_combat" ];
|
||||
self.run_override_weights = level._scr_anim[ self.animname ][ "run_weights" ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.pathTurnAnimOverrideFunc = animscripts\civilian\civilian_move::civilian_combatHunchedMoveTurn;
|
||||
|
||||
self.run_overrideanim = level._scr_anim[ "default_civilian" ][ "run_hunched_combat" ];
|
||||
self.run_override_weights = level._scr_anim[ "default_civilian" ][ "run_hunched_weights" ];
|
||||
|
||||
//now check if this animset defines it's own anims
|
||||
if ( IsDefined( level._scr_anim[ self.animname ][ "run_hunched_combat" ] ) )
|
||||
{
|
||||
self.run_overrideanim = level._scr_anim[ self.animname ][ "run_hunched_combat" ];
|
||||
self.run_override_weights = level._scr_anim[ self.animname ][ "run_hunched_weights" ];
|
||||
}
|
||||
}
|
||||
|
||||
self.run_overrideBulletReact = level._scr_anim[ "default_civilian" ][ "react_stumble" ];
|
||||
|
||||
//now check if this animset defines it's own anims
|
||||
if ( IsDefined( level._scr_anim[ self.animname ][ "react_stumble" ] ) )
|
||||
{
|
||||
self.run_overrideBulletReact = level._scr_anim[ self.animname ][ "react_stumble" ];
|
||||
}
|
||||
|
||||
self.walk_overrideanim = self.run_overrideanim;
|
||||
self.walk_override_weights = self.run_override_weights;
|
||||
|
||||
detachProps( self.civilian_walk_animation );
|
||||
}
|
||||
|
||||
|
||||
checkCombatState()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
wasInCombat = ( self.alertLevelInt > 1 );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
isInCombat = ( self.alertLevelInt > 1 );
|
||||
|
||||
if ( wasInCombat && !isInCombat )
|
||||
startNonCombat();
|
||||
else if ( !wasInCombat && isInCombat )
|
||||
startCombat();
|
||||
|
||||
wasInCombat = isInCombat;
|
||||
|
||||
wait 0.05; // TEMP make this an alert level change wait when code is in.
|
||||
}
|
||||
}
|
133
animscripts/civilian/civilian_move.gsc
Normal file
133
animscripts/civilian/civilian_move.gsc
Normal file
@ -0,0 +1,133 @@
|
||||
#include animscripts\Utility;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
animscripts\move::main();
|
||||
}
|
||||
|
||||
|
||||
civilian_nonCombatMoveTurn( angleDiff )
|
||||
{
|
||||
assert( isdefined( level._scr_anim[ self.animname ][ "turn_left_90" ] ) );
|
||||
assert( isdefined( level._scr_anim[ self.animname ][ "turn_right_90" ] ) );
|
||||
|
||||
turnAnim = undefined;
|
||||
|
||||
if ( angleDiff < -60 && angleDiff > -120 )
|
||||
turnAnim = level._scr_anim[ self.animname ][ "turn_left_90" ];
|
||||
|
||||
if ( angleDiff > 60 && angleDiff < 120 )
|
||||
turnAnim = level._scr_anim[ self.animname ][ "turn_right_90" ];
|
||||
|
||||
if ( isdefined( turnAnim ) && animscripts\move::pathChange_canDoTurnAnim( turnAnim ) )
|
||||
return turnAnim;
|
||||
else
|
||||
return undefined;
|
||||
}
|
||||
|
||||
//7 9 <- 8 is invalid, it's straight.
|
||||
//4 6 <- 5 is invalid, it's not a turn.
|
||||
//1 2 3
|
||||
civilian_combatMoveTurn( angleDiff )
|
||||
{
|
||||
turnDir = -1;
|
||||
turnAnim = undefined;
|
||||
|
||||
if ( angleDiff < -22.5 )
|
||||
{
|
||||
if ( angleDiff > -45 )
|
||||
turnDir = 7;
|
||||
else if ( angleDiff > -112.5 )
|
||||
turnDir = 4;
|
||||
else if ( angleDiff > -157.5 )
|
||||
turnDir = 1;
|
||||
else
|
||||
turnDir = 2;
|
||||
}
|
||||
else if ( angleDiff > 22.5 )
|
||||
{
|
||||
if ( angleDiff < 45 )
|
||||
turnDir = 9;
|
||||
else if ( angleDiff < 112.5 )
|
||||
turnDir = 6;
|
||||
else if ( angleDiff < 157.5 )
|
||||
turnDir = 3;
|
||||
else
|
||||
turnDir = 2;
|
||||
}
|
||||
|
||||
if ( IsDefined(level._scr_anim[ self.animname ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_turn" ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_turn" ][turnDir]) )
|
||||
{
|
||||
turnAnim = level._scr_anim[ self.animname ][ "run_combat_turn" ][turnDir];
|
||||
}
|
||||
|
||||
if ( IsDefined( turnAnim ) && animscripts\move::pathChange_canDoTurnAnim( turnAnim ) )
|
||||
return turnAnim;
|
||||
else
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
civilian_combatHunchedMoveTurn( angleDiff )
|
||||
{
|
||||
turnDir = -1;
|
||||
turnAnim = undefined;
|
||||
largeTurnAnim = undefined;
|
||||
|
||||
if ( angleDiff < -22.5 )
|
||||
{
|
||||
if ( angleDiff > -45 )
|
||||
turnDir = 7;
|
||||
else if ( angleDiff > -112.5 )
|
||||
turnDir = 4;
|
||||
else if ( angleDiff > -157.5 )
|
||||
turnDir = 1;
|
||||
else
|
||||
turnDir = 2;
|
||||
}
|
||||
else if ( angleDiff > 22.5 )
|
||||
{
|
||||
if ( angleDiff < 45 )
|
||||
turnDir = 9;
|
||||
else if ( angleDiff < 112.5 )
|
||||
turnDir = 6;
|
||||
else if ( angleDiff < 157.5 )
|
||||
turnDir = 3;
|
||||
else
|
||||
turnDir = 2;
|
||||
}
|
||||
|
||||
if ( IsDefined(level._scr_anim[ self.animname ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_hunched_large_turn" ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_hunched_large_turn" ][turnDir]) )
|
||||
{
|
||||
largeTurns = level._scr_anim[ self.animname ][ "run_combat_hunched_large_turn" ][turnDir];
|
||||
if ( largeTurns.size > 0 )
|
||||
{
|
||||
largeTurnAnim = largeTurns[RandomInt(largeTurns.size)];
|
||||
}
|
||||
else
|
||||
{
|
||||
largeTurnAnim = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
if ( IsDefined( largeTurnAnim ) && ( RandomInt( 3 ) < 2 ) && animscripts\move::pathChange_canDoTurnAnim( largeTurnAnim ) )
|
||||
return largeTurnAnim;
|
||||
|
||||
if ( IsDefined(level._scr_anim[ self.animname ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_hunched_turn" ])
|
||||
&& IsDefined(level._scr_anim[ self.animname ][ "run_combat_hunched_turn" ][turnDir]) )
|
||||
{
|
||||
turnAnim = level._scr_anim[ self.animname ][ "run_combat_hunched_turn" ][turnDir];
|
||||
}
|
||||
|
||||
if ( isdefined( turnAnim ) && animscripts\move::pathChange_canDoTurnAnim( turnAnim ) )
|
||||
return turnAnim;
|
||||
else
|
||||
return undefined;
|
||||
}
|
4
animscripts/civilian/civilian_scripted.gsc
Normal file
4
animscripts/civilian/civilian_scripted.gsc
Normal file
@ -0,0 +1,4 @@
|
||||
main()
|
||||
{
|
||||
animscripts\scripted::main();
|
||||
}
|
76
animscripts/civilian/lunar/civilian_init.gsc
Normal file
76
animscripts/civilian/lunar/civilian_init.gsc
Normal file
@ -0,0 +1,76 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
animscripts\lunar\init::main();
|
||||
|
||||
if ( !isdefined( level._initialized_civilian_animations ) )
|
||||
{
|
||||
initCivilianAnims();
|
||||
}
|
||||
|
||||
animscripts\civilian\civilian_init_common::civilian_init();
|
||||
|
||||
}
|
||||
|
||||
initCivilianAnims()
|
||||
{
|
||||
level._initialized_civilian_animations = true;
|
||||
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_combat" ] = [ %tp_moon_civ_run_combat ];
|
||||
level._scr_anim[ "default_civilian" ][ "run_weights" ] = common_scripts\utility::get_cumulative_weights( [ 1 ] );
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_noncombat" ] = [ %tp_moon_civ_run_noncombat ];
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "run_hunched_combat" ] = [ %tp_moon_civ_run_hunched_combat_A, %tp_moon_civ_run_hunched_combat_B, %tp_moon_civ_run_hunched_combat_C ];
|
||||
level._scr_anim[ "default_civilian" ][ "run_hunched_weights" ] = common_scripts\utility::get_cumulative_weights( [ 1, 1, 1 ] );
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "idle_noncombat" ] = [ %tp_moon_civ_idle_noncombat ];
|
||||
level._scr_anim[ "default_civilian" ][ "idle_combat" ] = [ %tp_moon_civ_idle_combat_A, %tp_moon_civ_idle_combat_B ];
|
||||
level._scr_anim[ "default_civilian" ][ "dodge_left" ] = %tp_moon_civ_dodge_L;
|
||||
level._scr_anim[ "default_civilian" ][ "dodge_right" ] = %tp_moon_civ_dodge_R;
|
||||
level._scr_anim[ "default_civilian" ][ "react_stumble" ] = [ %tp_moon_civ_react_stumble ];
|
||||
|
||||
level._scr_anim[ "default_civilian" ][ "turn_left_90" ] = %tp_moon_civ_run_noncombat_turn_L90;
|
||||
level._scr_anim[ "default_civilian" ][ "turn_right_90" ] = %tp_moon_civ_run_noncombat_turn_R90;
|
||||
|
||||
//7 9 <- 8 is invalid, it's straight.
|
||||
//4 6 <- 5 is invalid, it's not a turn.
|
||||
//1 2 3
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][1] = %tp_moon_civ_run_combat_turn_L135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][2] = %tp_moon_civ_run_combat_turn_180;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][3] = %tp_moon_civ_run_combat_turn_R135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][4] = %tp_moon_civ_run_combat_turn_L90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][6] = %tp_moon_civ_run_combat_turn_R90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][7] = %tp_moon_civ_run_combat_turn_L45;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_turn"][9] = %tp_moon_civ_run_combat_turn_R45;
|
||||
|
||||
|
||||
|
||||
//define these if we want hunched turns, they aren't required though.
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][1] = %tp_moon_civ_run_combat_turn_L135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][2] = %tp_moon_civ_run_combat_turn_180;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][3] = %tp_moon_civ_run_combat_turn_R135;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][4] = %tp_moon_civ_run_combat_hunched_turnL90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][6] = %tp_moon_civ_run_combat_hunched_turnR90;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][7] = %tp_moon_civ_run_combat_hunched_turnL45;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_turn"][9] = %tp_moon_civ_run_combat_hunched_turnR45;
|
||||
/*
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][1] = undefined;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][2] = undefined;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][3] = undefined;
|
||||
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][4] = [ %tp_moon_civ_run_combat_hunched_large_turnL90_slide, %tp_moon_civ_run_combat_hunched_large_turnL90_stumble ];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][6] = [ %tp_moon_civ_run_combat_hunched_large_turnR90_slide, %tp_moon_civ_run_combat_hunched_large_turnR90_stumble ];
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][7] = undefined;
|
||||
level._scr_anim[ "default_civilian"]["run_combat_hunched_large_turn"][9] = undefined;
|
||||
*/
|
||||
}
|
||||
|
1532
animscripts/combat.gsc
Normal file
1532
animscripts/combat.gsc
Normal file
File diff suppressed because it is too large
Load Diff
15
animscripts/combat_say.gsc
Normal file
15
animscripts/combat_say.gsc
Normal file
@ -0,0 +1,15 @@
|
||||
// combat_say.gsc
|
||||
// Determines when to talk during combat.
|
||||
|
||||
// Plays miscellaneous combat lines sometimes during combat
|
||||
generic_combat()
|
||||
{
|
||||
self animscripts\battlechatter::playBattleChatter();
|
||||
}
|
||||
|
||||
// Plays vaguely context-sensitive combat lines sometimes during combat
|
||||
specific_combat( dialogueLine )
|
||||
{
|
||||
self animscripts\battlechatter::playBattleChatter();
|
||||
}
|
||||
|
2258
animscripts/combat_utility.gsc
Normal file
2258
animscripts/combat_utility.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1402
animscripts/corner.gsc
Normal file
1402
animscripts/corner.gsc
Normal file
File diff suppressed because it is too large
Load Diff
2460
animscripts/cover_arrival.gsc
Normal file
2460
animscripts/cover_arrival.gsc
Normal file
File diff suppressed because it is too large
Load Diff
979
animscripts/cover_behavior.gsc
Normal file
979
animscripts/cover_behavior.gsc
Normal file
@ -0,0 +1,979 @@
|
||||
#include maps\_utility;
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\utility;
|
||||
#include animscripts\shared;
|
||||
#include common_scripts\utility;
|
||||
|
||||
/*
|
||||
This file contains the overall behavior for all "whack-a-mole" cover nodes.
|
||||
|
||||
Callbacks which must be defined:
|
||||
|
||||
All callbacks should return true or false depending on whether they succeeded in doing something.
|
||||
If functionality for a callback isn't available, just don't define it.
|
||||
|
||||
mainLoopStart()
|
||||
optional
|
||||
reload()
|
||||
plays a reload animation in a hidden position
|
||||
leaveCoverAndShoot()
|
||||
does the main attacking; steps out or stands up and fires, goes back to hiding.
|
||||
should obey orders from decideWhatAndHowToShoot in shoot_behavior.gsc.
|
||||
look( maxtime )
|
||||
looks for up to maxtime, stopping and returning if enemy becomes visible or if suppressed
|
||||
fastlook()
|
||||
looks quickly
|
||||
idle()
|
||||
idles until the "end_idle" notify.
|
||||
flinch()
|
||||
flinches briefly (1-2 seconds), doesn't need to return true or false.
|
||||
grenade( throwAt )
|
||||
steps out and throws a grenade at the given player / ai
|
||||
grenadehidden( throwAt )
|
||||
throws a grenade at the given player / ai without leaving cover
|
||||
blindfire()
|
||||
blindfires from cover
|
||||
|
||||
example:
|
||||
behaviorCallbacks = spawnstruct();
|
||||
behaviorCallbacks.reload = ::reload;
|
||||
...
|
||||
animscripts\cover_behavior::main( behaviorCallbacks );
|
||||
|
||||
*/
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
MELEE_GRACE_PERIOD_REQUIRED_TIME = 3000;
|
||||
MELEE_GRACE_PERIOD_GIVEN_TIME = 5000;
|
||||
|
||||
main( behaviorCallbacks )
|
||||
{
|
||||
self.couldntSeeEnemyPos = self.origin;// ( set couldntSeeEnemyPos to a place the enemy can't be while we're in corner behavior )
|
||||
|
||||
behaviorStartTime = gettime();
|
||||
coverTimers = spawnstruct();
|
||||
coverTimers.nextAllowedLookTime = behaviorStartTime - 1;
|
||||
coverTimers.nextAllowedSuppressTime = behaviorStartTime - 1;
|
||||
|
||||
// we won't look for better cover purely out of boredom until this time
|
||||
resetLookForBetterCoverTime();
|
||||
resetRespondToDeathTime();
|
||||
|
||||
self.seekOutEnemyTime = gettime();
|
||||
|
||||
self.a.lastEncounterTime = behaviorStartTime;
|
||||
self.a.idlingAtCover = false;
|
||||
self.a.movement = "stop";
|
||||
|
||||
// if we break out of cover mode after this time, we will get a grace period during which we can melee charge the player
|
||||
self.meleeCoverChargeMinTime = behaviorStartTime + MELEE_GRACE_PERIOD_REQUIRED_TIME;
|
||||
|
||||
/#
|
||||
if ( getdvar( "scr_coveridle" ) == "1" )
|
||||
self.coverNode.script_onlyidle = true;
|
||||
#/
|
||||
|
||||
self thread watchSuppression();
|
||||
|
||||
desynched = ( gettime() > 2500 );
|
||||
|
||||
correctAngles = getCorrectCoverAngles();
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( shouldHelpAdvancingTeammate() )
|
||||
{
|
||||
if ( tryRunningToEnemy( true ) )
|
||||
{
|
||||
wait 0.05;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( isdefined( behaviorCallbacks.mainLoopStart ) )
|
||||
{
|
||||
startTime = gettime();
|
||||
self thread endIdleAtFrameEnd();
|
||||
|
||||
[[ behaviorCallbacks.mainLoopStart ]]();
|
||||
|
||||
if ( gettime() == startTime )
|
||||
self notify( "dont_end_idle" );
|
||||
}
|
||||
|
||||
if ( isdefined( behaviorCallbacks.moveToNearByCover ) )
|
||||
{
|
||||
if ( [[ behaviorCallbacks.moveToNearByCover ]]() )
|
||||
continue;
|
||||
}
|
||||
|
||||
// tagJW<NOTE>: We do not need or want to teleport the actor when locked to an object
|
||||
if ( !self isLinked() )
|
||||
{
|
||||
self safeTeleport( self.covernode.origin, correctAngles );
|
||||
}
|
||||
|
||||
if ( !desynched )
|
||||
{
|
||||
idle( behaviorCallbacks, 0.05 + randomfloat( 1.5 ) );
|
||||
desynched = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( doNonAttackCoverBehavior( behaviorCallbacks ) )
|
||||
continue;
|
||||
|
||||
if ( isdefined( anim.throwGrenadeAtPlayerASAP ) && isAlive( level._player ) )
|
||||
{
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, level._player ) )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( respondToDeadTeammate() )
|
||||
return;
|
||||
|
||||
// determine visibility and suppressability of enemy.
|
||||
visibleEnemy = false;
|
||||
suppressableEnemy = false;
|
||||
if ( isalive( self.enemy ) )
|
||||
{
|
||||
visibleEnemy = isEnemyVisibleFromExposed();
|
||||
suppressableEnemy = canSuppressEnemyFromExposed();
|
||||
}
|
||||
|
||||
// decide what to do.
|
||||
if ( visibleEnemy )
|
||||
{
|
||||
if ( self.a.getBoredOfThisNodeTime < gettime() )
|
||||
{
|
||||
if ( lookForBetterCover() )
|
||||
return;
|
||||
}
|
||||
|
||||
attackVisibleEnemy( behaviorCallbacks );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isdefined( self.aggressiveMode ) || enemyIsHiding() )
|
||||
{
|
||||
if ( advanceOnHidingEnemy() )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( suppressableEnemy )
|
||||
{
|
||||
attackSuppressableEnemy( behaviorCallbacks, coverTimers );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( attackNothingToDo( behaviorCallbacks, coverTimers ) )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
end_script( coverMode )
|
||||
{
|
||||
self.turnToMatchNode = undefined;
|
||||
self.a.prevAttack = undefined;
|
||||
|
||||
if ( isDefined( self.meleeCoverChargeMinTime ) && (self.meleeCoverChargeMinTime <= getTime()) )
|
||||
{
|
||||
// give the AI a chance to charge the player if he forced him out of cover
|
||||
self.meleeCoverChargeGraceEndTime = getTime() + MELEE_GRACE_PERIOD_GIVEN_TIME;
|
||||
self.meleeCoverChargeMinTime = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getCorrectCoverAngles()
|
||||
{
|
||||
correctAngles = ( self.coverNode.angles[ 0 ], getNodeForwardYaw( self.coverNode ), self.coverNode.angles[ 2 ] );
|
||||
return correctAngles;
|
||||
}
|
||||
|
||||
|
||||
RESPOND_TO_DEATH_RETRY_INTERVAL = 30 * 1000;
|
||||
|
||||
respondToDeadTeammate()
|
||||
{
|
||||
if ( self atDangerousNode() && self.a.respondToDeathTime < gettime() )
|
||||
{
|
||||
if ( lookForBetterCover() )
|
||||
return true;
|
||||
|
||||
self.a.respondToDeathTime = gettime() + RESPOND_TO_DEATH_RETRY_INTERVAL;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
doNonAttackCoverBehavior( behaviorCallbacks )
|
||||
{
|
||||
/#
|
||||
if ( isDefined( self.coverNode.script_onlyidle ) )
|
||||
{
|
||||
assert( self.coverNode.script_onlyidle );// true or undefined
|
||||
idle( behaviorCallbacks );
|
||||
return true;
|
||||
}
|
||||
#/
|
||||
|
||||
// if we're suppressed, we do other things.
|
||||
if ( suppressedBehavior( behaviorCallbacks ) )
|
||||
{
|
||||
if ( isEnemyVisibleFromExposed() )
|
||||
resetSeekOutEnemyTime();
|
||||
self.a.lastEncounterTime = gettime();
|
||||
return true;
|
||||
}
|
||||
|
||||
// reload if we need to; everything in this loop involves shooting.
|
||||
if ( coverReload( behaviorCallbacks, 0 ) )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
attackVisibleEnemy( behaviorCallbacks )
|
||||
{
|
||||
if ( distanceSquared( self.origin, self.enemy.origin ) > 750 * 750 )
|
||||
{
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, self.enemy ) )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( leaveCoverAndShoot( behaviorCallbacks, "normal" ) )
|
||||
{
|
||||
resetSeekOutEnemyTime();
|
||||
self.a.lastEncounterTime = gettime();
|
||||
}
|
||||
else
|
||||
{
|
||||
idle( behaviorCallbacks );
|
||||
}
|
||||
}
|
||||
|
||||
attackSuppressableEnemy( behaviorCallbacks, coverTimers )
|
||||
{
|
||||
if ( self.doingAmbush )
|
||||
{
|
||||
if ( leaveCoverAndShoot( behaviorCallbacks, "ambush" ) )
|
||||
return;
|
||||
}
|
||||
else if ( self.provideCoveringFire || gettime() >= coverTimers.nextAllowedSuppressTime )
|
||||
{
|
||||
preferredActivity = "suppress";
|
||||
if ( !self.provideCoveringFire && ( gettime() - self.lastSuppressionTime ) > 5000 && randomint( 3 ) < 2 )
|
||||
preferredActivity = "ambush";
|
||||
else if ( !self animscripts\shoot_behavior::shouldSuppress() )
|
||||
preferredActivity = "ambush";
|
||||
|
||||
if ( leaveCoverAndShoot( behaviorCallbacks, preferredActivity ) )
|
||||
{
|
||||
coverTimers.nextAllowedSuppressTime = gettime() + randomintrange( 3000, 20000 );
|
||||
// if they're there, we've seen them
|
||||
if ( isEnemyVisibleFromExposed() )
|
||||
self.a.lastEncounterTime = gettime();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, self.enemy ) )
|
||||
return;
|
||||
|
||||
idle( behaviorCallbacks );
|
||||
}
|
||||
|
||||
|
||||
attackNothingToDo( behaviorCallbacks, coverTimers )
|
||||
{
|
||||
if ( coverReload( behaviorCallbacks, 0.1 ) )
|
||||
return false;
|
||||
|
||||
if ( isdefined( self.enemy ) )
|
||||
{
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, self.enemy ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !self.doingAmbush && gettime() >= coverTimers.nextAllowedLookTime )
|
||||
{
|
||||
if ( lookForEnemy( behaviorCallbacks ) )
|
||||
{
|
||||
coverTimers.nextAllowedLookTime = gettime() + randomintrange( 4000, 15000 );
|
||||
|
||||
// if they're there, we've seen them
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// we're *really* bored right now
|
||||
if ( gettime() > self.a.getBoredOfThisNodeTime )
|
||||
{
|
||||
if ( cantFindAnythingToDo() )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( self.doingAmbush || ( gettime() >= coverTimers.nextAllowedSuppressTime && isdefined( self.enemy ) ) )
|
||||
{
|
||||
// be ready to ambush them if they happen to show up
|
||||
if ( leaveCoverAndShoot( behaviorCallbacks, "ambush" ) )
|
||||
{
|
||||
if ( isEnemyVisibleFromExposed() )
|
||||
resetSeekOutEnemyTime();
|
||||
self.a.lastEncounterTime = gettime();
|
||||
coverTimers.nextAllowedSuppressTime = gettime() + randomintrange( 6000, 20000 );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
idle( behaviorCallbacks );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
isEnemyVisibleFromExposed()
|
||||
{
|
||||
if ( !isdefined( self.enemy ) )
|
||||
return false;
|
||||
|
||||
// if we couldn't see our enemy last time we stepped out, and they haven't moved, assume we still can't see them.
|
||||
if ( distanceSquared( self.enemy.origin, self.couldntSeeEnemyPos ) < 16 * 16 )
|
||||
return false;
|
||||
else
|
||||
return canSeeEnemyFromExposed();
|
||||
}
|
||||
|
||||
suppressedBehavior( behaviorCallbacks )
|
||||
{
|
||||
if ( !isSuppressedWrapper() )
|
||||
return false;
|
||||
|
||||
nextAllowedBlindfireTime = gettime();
|
||||
|
||||
justlooked = true;
|
||||
|
||||
//prof_begin( "suppressedBehavior" );
|
||||
|
||||
while ( isSuppressedWrapper() )
|
||||
{
|
||||
justlooked = false;
|
||||
|
||||
// tagJW<NOTE>: We do not need or want to teleport the actor when locked to an object
|
||||
if ( !self isLinked() )
|
||||
{
|
||||
self safeTeleport( self.coverNode.origin );
|
||||
}
|
||||
|
||||
tryMovingNodes = true;
|
||||
|
||||
// guys that favor blindfire should try to blindfire instead of move a lot more
|
||||
if ( isdefined( self.favor_blindfire ) )
|
||||
tryMovingNodes = coinToss();
|
||||
|
||||
if ( tryMovingNodes && !isdefined( self.locked_combat ) )
|
||||
{
|
||||
if ( tryToGetOutOfDangerousSituation( behaviorCallbacks ) )
|
||||
{
|
||||
self notify( "killanimscript" );
|
||||
//prof_end( "suppressedBehavior" );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// if we're only at a concealment node, and it's not providing cover, we shouldn't try to use the cover to keep us safe!
|
||||
if ( self.a.atConcealmentNode && self canSeeEnemy() )
|
||||
{
|
||||
//prof_end( "suppressedBehavior" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isEnemyVisibleFromExposed() || canSuppressEnemyFromExposed() )
|
||||
{
|
||||
if ( isdefined( anim.throwGrenadeAtPlayerASAP ) && isAlive( level._player ) )
|
||||
{
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, level._player ) )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( coverReload( behaviorCallbacks, 0 ) )
|
||||
continue;
|
||||
|
||||
if ( self.team != "allies" && gettime() >= nextAllowedBlindfireTime )
|
||||
{
|
||||
if ( blindfire( behaviorCallbacks ) )
|
||||
{
|
||||
nextAllowedBlindfireTime = gettime();
|
||||
if ( !isdefined( self.favor_blindfire ) )
|
||||
nextAllowedBlindfireTime += randomintrange( 3000, 12000 );
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( tryThrowingGrenade( behaviorCallbacks, self.enemy ) )
|
||||
{
|
||||
justlooked = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( coverReload( behaviorCallbacks, 0.1 ) )
|
||||
continue;
|
||||
|
||||
//prof_end( "suppressedBehavior" );
|
||||
idle( behaviorCallbacks );
|
||||
}
|
||||
|
||||
if ( !justlooked && randomint( 2 ) == 0 )
|
||||
lookfast( behaviorCallbacks );
|
||||
|
||||
//prof_end( "suppressedBehavior" );
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns array of integers 0 through n-1, in random order
|
||||
getPermutation( n )
|
||||
{
|
||||
permutation = [];
|
||||
assert( n > 0 );
|
||||
if ( n == 1 )
|
||||
{
|
||||
permutation[ 0 ] = 0;
|
||||
}
|
||||
else if ( n == 2 )
|
||||
{
|
||||
permutation[ 0 ] = randomint( 2 );
|
||||
permutation[ 1 ] = 1 - permutation[ 0 ];
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < n; i++ )
|
||||
permutation[ i ] = i;
|
||||
for ( i = 0; i < n; i++ )
|
||||
{
|
||||
switchIndex = i + randomint( n - i );
|
||||
temp = permutation[ switchIndex ];
|
||||
permutation[ SwitchIndex ] = permutation[ i ];
|
||||
permutation[ i ] = temp;
|
||||
}
|
||||
}
|
||||
return permutation;
|
||||
}
|
||||
|
||||
callOptionalBehaviorCallback( callback, arg, arg2, arg3 )
|
||||
{
|
||||
if ( !isdefined( callback ) )
|
||||
return false;
|
||||
|
||||
//prof_begin( "callOptionalBehaviorCallback" );
|
||||
self thread endIdleAtFrameEnd();
|
||||
|
||||
starttime = gettime();
|
||||
|
||||
val = undefined;
|
||||
if ( isdefined( arg3 ) )
|
||||
val = [[ callback ]]( arg, arg2, arg3 );
|
||||
else if ( isdefined( arg2 ) )
|
||||
val = [[ callback ]]( arg, arg2 );
|
||||
else if ( isdefined( arg ) )
|
||||
val = [[ callback ]]( arg );
|
||||
else
|
||||
val = [[ callback ]]();
|
||||
|
||||
/#
|
||||
// if this assert fails, a behaviorCallback callback didn't return true or false.
|
||||
assert( isdefined( val ) && ( val == true || val == false ) );
|
||||
|
||||
// behaviorCallbacks must return true if and only if they let time pass.
|
||||
// (it is also important that they only let time pass if they did what they were supposed to do,
|
||||
// but that's not so easy to enforce.)
|
||||
if ( val )
|
||||
assert( gettime() != starttime );
|
||||
else
|
||||
assert( gettime() == starttime );
|
||||
#/
|
||||
|
||||
if ( !val )
|
||||
self notify( "dont_end_idle" );
|
||||
|
||||
//prof_end( "callOptionalBehaviorCallback" );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
watchSuppression()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
// self.lastSuppressionTime is the last time a bullet whizzed by.
|
||||
// self.suppressionStart is the last time we were thinking it was safe when a bullet whizzed by.
|
||||
|
||||
self.lastSuppressionTime = gettime() - 100000;
|
||||
self.suppressionStart = self.lastSuppressionTime;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "suppression" );
|
||||
|
||||
time = gettime();
|
||||
if ( self.lastSuppressionTime < time - 700 )
|
||||
self.suppressionStart = time;
|
||||
self.lastSuppressionTime = time;
|
||||
}
|
||||
}
|
||||
|
||||
coverReload( behaviorCallbacks, threshold )
|
||||
{
|
||||
if ( self.bulletsInClip > weaponClipSize( self.weapon ) * threshold )
|
||||
return false;
|
||||
|
||||
self.isreloading = true;
|
||||
|
||||
result = callOptionalBehaviorCallback( behaviorCallbacks.reload );
|
||||
|
||||
self.isreloading = false;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// initialGoal can be either "normal", "suppress", or "ambush".
|
||||
leaveCoverAndShoot( behaviorCallbacks, initialGoal )
|
||||
{
|
||||
self thread animscripts\shoot_behavior::decideWhatAndHowToShoot( initialGoal );
|
||||
|
||||
if ( !self.fixedNode && !self.doingAmbush && !isdefined( self.locked_combat ) )
|
||||
self thread breakOutOfShootingIfWantToMoveUp();
|
||||
|
||||
val = callOptionalBehaviorCallback( behaviorCallbacks.leaveCoverAndShoot );
|
||||
|
||||
self notify( "stop_deciding_how_to_shoot" );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
lookForEnemy( behaviorCallbacks )
|
||||
{
|
||||
if ( self.a.atConcealmentNode && self canSeeEnemy() )
|
||||
return false;
|
||||
|
||||
if ( self.a.lastEncounterTime + 6000 > gettime() )
|
||||
{
|
||||
return lookfast( behaviorCallbacks );
|
||||
}
|
||||
else
|
||||
{
|
||||
// look slow if possible
|
||||
result = callOptionalBehaviorCallback( behaviorCallbacks.look, 2 + randomfloat( 2 ) );
|
||||
if ( result )
|
||||
return true;
|
||||
return callOptionalBehaviorCallback( behaviorCallbacks.fastlook );
|
||||
}
|
||||
}
|
||||
|
||||
lookfast( behaviorCallbacks )
|
||||
{
|
||||
// look fast if possible
|
||||
result = callOptionalBehaviorCallback( behaviorCallbacks.fastlook );
|
||||
if ( result )
|
||||
return true;
|
||||
return callOptionalBehaviorCallback( behaviorCallbacks.look, 0 );
|
||||
}
|
||||
|
||||
idle( behaviorCallbacks, howLong )
|
||||
{
|
||||
self.flinching = false;
|
||||
|
||||
if ( isdefined( behaviorCallbacks.flinch ) )
|
||||
{
|
||||
// flinch if we just started getting shot at very recently
|
||||
if ( !self.a.idlingAtCover && gettime() - self.suppressionStart < 600 )
|
||||
{
|
||||
if ( [[ behaviorCallbacks.flinch ]]() )
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if bullets aren't already whizzing by, idle for now but flinch if we get incoming fire
|
||||
self thread flinchWhenSuppressed( behaviorCallbacks );
|
||||
}
|
||||
}
|
||||
|
||||
if ( !self.a.idlingAtCover )
|
||||
{
|
||||
assert( isdefined( behaviorCallbacks.idle ) );// idle must be available!
|
||||
self thread idleThread( behaviorCallbacks.idle );// this thread doesn't stop until "end_idle", which must be notified before we start anything else! use endIdleAtFrameEnd() to do this.
|
||||
self.a.idlingAtCover = true;
|
||||
}
|
||||
|
||||
if ( isdefined( howLong ) )
|
||||
self idleWait( howLong );
|
||||
else
|
||||
self idleWaitABit();
|
||||
|
||||
if ( self.flinching )
|
||||
self waittill( "flinch_done" );
|
||||
|
||||
self notify( "stop_waiting_to_flinch" );
|
||||
}
|
||||
|
||||
idleWait( howLong )
|
||||
{
|
||||
self endon( "end_idle" );
|
||||
wait howLong;
|
||||
}
|
||||
|
||||
idleWaitAbit()
|
||||
{
|
||||
self endon( "end_idle" );
|
||||
wait 0.3 + randomfloat( 0.1 );
|
||||
self waittill( "do_slow_things" );
|
||||
}
|
||||
|
||||
idleThread( idlecallback )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self [[ idlecallback ]]();
|
||||
}
|
||||
|
||||
flinchWhenSuppressed( behaviorCallbacks )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop_waiting_to_flinch" );
|
||||
|
||||
lastSuppressionTime = self.lastSuppressionTime;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "suppression" );
|
||||
|
||||
time = gettime();
|
||||
|
||||
if ( lastSuppressionTime < time - 2000 )
|
||||
break;
|
||||
|
||||
lastSuppressionTime = time;
|
||||
}
|
||||
|
||||
self.flinching = true;
|
||||
|
||||
self thread endIdleAtFrameEnd();
|
||||
|
||||
assert( isdefined( behaviorCallbacks.flinch ) );
|
||||
val = [[ behaviorCallbacks.flinch ]]();
|
||||
|
||||
if ( !val )
|
||||
self notify( "dont_end_idle" );
|
||||
|
||||
self.flinching = false;
|
||||
self notify( "flinch_done" );
|
||||
}
|
||||
|
||||
endIdleAtFrameEnd()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "dont_end_idle" );
|
||||
waittillframeend;
|
||||
|
||||
if ( !isdefined( self ) )
|
||||
return;
|
||||
|
||||
self notify( "end_idle" );
|
||||
self.a.idlingAtCover = false;
|
||||
}
|
||||
|
||||
tryThrowingGrenade( behaviorCallbacks, throwAt )
|
||||
{
|
||||
assert( isdefined( throwAt ) );
|
||||
|
||||
// don't throw backwards
|
||||
forward = anglesToForward( self.angles );
|
||||
dir = vectorNormalize( throwAt.origin - self.origin );
|
||||
if ( vectorDot( forward, dir ) < 0 )
|
||||
return false;
|
||||
|
||||
if ( self.doingAmbush && !recentlySawEnemy() )
|
||||
return false;
|
||||
|
||||
if ( self isPartiallySuppressedWrapper() )
|
||||
{
|
||||
return callOptionalBehaviorCallback( behaviorCallbacks.grenadehidden, throwAt );
|
||||
}
|
||||
else
|
||||
{
|
||||
return callOptionalBehaviorCallback( behaviorCallbacks.grenade, throwAt );
|
||||
}
|
||||
}
|
||||
|
||||
blindfire( behaviorCallbacks )
|
||||
{
|
||||
if ( !canBlindFire() )
|
||||
return false;
|
||||
|
||||
return callOptionalBehaviorCallback( behaviorCallbacks.blindfire );
|
||||
}
|
||||
|
||||
// Need this?
|
||||
breakOutOfShootingIfWantToMoveUp()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop_deciding_how_to_shoot" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( self.fixedNode || self.doingAmbush )
|
||||
return;
|
||||
|
||||
wait 0.5 + randomfloat( 0.75 );
|
||||
|
||||
if ( !isdefined( self.enemy ) )
|
||||
continue;
|
||||
|
||||
if ( enemyIsHiding() )
|
||||
{
|
||||
if ( advanceOnHidingEnemy() )
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !self recentlySawEnemy() && !self canSuppressEnemy() )
|
||||
{
|
||||
if ( gettime() > self.a.getBoredOfThisNodeTime )
|
||||
{
|
||||
if ( cantFindAnythingToDo() )
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enemyIsHiding()
|
||||
{
|
||||
// if this function is called, we already know that our enemy is not visible from exposed.
|
||||
// check to see if they're doing anything hiding-like.
|
||||
|
||||
if ( !isdefined( self.enemy ) )
|
||||
return false;
|
||||
|
||||
if ( self.enemy isFlashed() )
|
||||
return true;
|
||||
|
||||
if ( isplayer( self.enemy ) )
|
||||
{
|
||||
if ( isdefined( self.enemy.health ) && self.enemy.health < self.enemy.maxhealth )
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isAI( self.enemy ) && self.enemy isSuppressedWrapper() )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( isdefined( self.enemy.isreloading ) && self.enemy.isreloading )
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
resetRespondToDeathTime()
|
||||
{
|
||||
self.a.respondToDeathTime = 0;
|
||||
}
|
||||
|
||||
|
||||
resetLookForBetterCoverTime()
|
||||
{
|
||||
currentTime = gettime();
|
||||
|
||||
// treat group of shuffle nodes as one node, don't increase getBoredOfThisNodeTime by too much
|
||||
if ( isdefined( self.didShuffleMove ) && currentTime > self.a.getBoredOfThisNodeTime )
|
||||
{
|
||||
self.a.getBoredOfThisNodeTime = currentTime + randomintrange( 2000, 5000 );
|
||||
}
|
||||
else if ( isdefined( self.enemy ) )
|
||||
{
|
||||
dist = distance2D( self.origin, self.enemy.origin );
|
||||
if ( dist < self.engageMinDist )
|
||||
self.a.getBoredOfThisNodeTime = currentTime + randomintrange( 5000, 10000 );
|
||||
else if ( dist > self.engageMaxDist && dist < self.goalradius )
|
||||
self.a.getBoredOfThisNodeTime = currentTime + randomintrange( 2000, 5000 );
|
||||
else
|
||||
self.a.getBoredOfThisNodeTime = currentTime + randomintrange( 10000, 15000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.getBoredOfThisNodeTime = currentTime + randomintrange( 5000, 15000 );
|
||||
}
|
||||
}
|
||||
|
||||
resetSeekOutEnemyTime()
|
||||
{
|
||||
// we'll be willing to actually run right up to our enemy in order to find them if we haven't seen them by this time.
|
||||
// however, we'll try to find better cover before seeking them out
|
||||
if ( isdefined( self.aggressiveMode ) )
|
||||
self.seekOutEnemyTime = gettime() + randomintrange( 500, 1000 );
|
||||
else
|
||||
self.seekOutEnemyTime = gettime() + randomintrange( 3000, 5000 );
|
||||
}
|
||||
|
||||
// these next functions are "look for better cover" functions.
|
||||
// they don't always need to cause the actor to leave the node immediately,
|
||||
// but if they keep being called over and over they need to become more and more likely to do so,
|
||||
// as this indicates that new cover is strongly needed.
|
||||
cantFindAnythingToDo()
|
||||
{
|
||||
return advanceOnHidingEnemy();
|
||||
}
|
||||
|
||||
advanceOnHidingEnemy()
|
||||
{
|
||||
if ( self.fixedNode || self.doingAmbush )
|
||||
return false;
|
||||
|
||||
if ( isdefined( self.aggressiveMode ) && gettime() >= self.seekOutEnemyTime )
|
||||
{
|
||||
return tryRunningToEnemy( false );
|
||||
}
|
||||
|
||||
foundBetterCover = false;
|
||||
if ( !isdefined( self.enemy ) || !self.enemy isFlashed() )
|
||||
foundBetterCover = lookForBetterCover();
|
||||
|
||||
if ( !foundBetterCover && isdefined( self.enemy ) && !self canSeeEnemyFromExposed() )
|
||||
{
|
||||
if ( gettime() >= self.seekOutEnemyTime )
|
||||
{
|
||||
return tryRunningToEnemy( false );
|
||||
}
|
||||
}
|
||||
|
||||
// maybe at this point we could look for someone who's suppressing our enemy,
|
||||
// and if someone is, we can say "cover me!" and have them say "i got you covered" or something.
|
||||
|
||||
return foundBetterCover;
|
||||
}
|
||||
|
||||
tryToGetOutOfDangerousSituation( behaviorCallbacks )
|
||||
{
|
||||
if ( isdefined( behaviorCallbacks.moveToNearByCover ) )
|
||||
{
|
||||
if ( [[ behaviorCallbacks.moveToNearByCover ]]() )
|
||||
return true;
|
||||
}
|
||||
|
||||
return lookForBetterCover();
|
||||
}
|
||||
|
||||
// TEMP move these into animsets
|
||||
set_standing_turns()
|
||||
{
|
||||
self.a.array[ "turn_left_45" ] = %exposed_tracking_turn45L;
|
||||
self.a.array[ "turn_left_90" ] = %exposed_tracking_turn90L;
|
||||
self.a.array[ "turn_left_135" ] = %exposed_tracking_turn135L;
|
||||
self.a.array[ "turn_left_180" ] = %exposed_tracking_turn180L;
|
||||
self.a.array[ "turn_right_45" ] = %exposed_tracking_turn45R;
|
||||
self.a.array[ "turn_right_90" ] = %exposed_tracking_turn90R;
|
||||
self.a.array[ "turn_right_135" ] = %exposed_tracking_turn135R;
|
||||
self.a.array[ "turn_right_180" ] = %exposed_tracking_turn180R;
|
||||
}
|
||||
|
||||
set_crouching_turns()
|
||||
{
|
||||
self.a.array[ "turn_left_45" ] = %exposed_crouch_turn_90_left;
|
||||
self.a.array[ "turn_left_90" ] = %exposed_crouch_turn_90_left;
|
||||
self.a.array[ "turn_left_135" ] = %exposed_crouch_turn_180_left;
|
||||
self.a.array[ "turn_left_180" ] = %exposed_crouch_turn_180_left;
|
||||
self.a.array[ "turn_right_45" ] = %exposed_crouch_turn_90_right;
|
||||
self.a.array[ "turn_right_90" ] = %exposed_crouch_turn_90_right;
|
||||
self.a.array[ "turn_right_135" ] = %exposed_crouch_turn_180_right;
|
||||
self.a.array[ "turn_right_180" ] = %exposed_crouch_turn_180_right;
|
||||
}
|
||||
|
||||
|
||||
turnToMatchNodeDirection( nodeAngleOffset )
|
||||
{
|
||||
if ( isdefined( self.node ) )
|
||||
{
|
||||
node = self.node;
|
||||
|
||||
absRelYaw = abs( AngleClamp180( self.angles[1] - ( node.angles[1] + nodeAngleOffset ) ) );
|
||||
|
||||
if ( self.a.pose == "stand" && node getHighestNodeStance() != "stand" )
|
||||
{
|
||||
if ( absRelYaw > 45 && absRelYaw < 90 )
|
||||
self orientmode( "face angle", self.angles[1] );
|
||||
else
|
||||
self orientmode( "face current" );
|
||||
|
||||
rate = 1.5;
|
||||
noteTime = getNotetrackTimes( %exposed_stand_2_crouch, "anim_pose = \"crouch\"" )[0];
|
||||
noteTime = min( 1, noteTime * 1.1 );
|
||||
time = noteTime * getAnimLength( %exposed_stand_2_crouch ) / rate;
|
||||
|
||||
self setflaggedanimknoballrestart( "crouchanim", %exposed_stand_2_crouch, %body, 1, .2, rate );
|
||||
self animscripts\shared::DoNoteTracksForTime( time, "crouchanim" );
|
||||
self clearanim( %body, 0.2 );
|
||||
}
|
||||
|
||||
self orientmode( "face angle", self.angles[1] );
|
||||
|
||||
relYaw = AngleClamp180( self.angles[1] - ( node.angles[1] + nodeAngleOffset ) );
|
||||
|
||||
if ( abs( relYaw ) > 45 )
|
||||
{
|
||||
if ( self.a.pose == "stand" )
|
||||
set_standing_turns();
|
||||
else
|
||||
set_crouching_turns();
|
||||
|
||||
self.turnThreshold = 45;
|
||||
self.turnToMatchNode = true;
|
||||
animscripts\combat::TurnToFaceRelativeYaw( relYaw );
|
||||
self.turnToMatchNode = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveToNearbyCover()
|
||||
{
|
||||
if ( !isdefined( self.enemy ) )
|
||||
return false;
|
||||
|
||||
if ( isdefined( self.didShuffleMove ) )
|
||||
{
|
||||
self.didShuffleMove = undefined;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( !isdefined( self.node ) )
|
||||
return false;
|
||||
|
||||
if ( randomint( 3 ) == 0 )
|
||||
return false;
|
||||
|
||||
if ( self.fixedNode || self.doingAmbush || self.keepClaimedNode || self.keepClaimedNodeIfValid )
|
||||
return false;
|
||||
|
||||
if ( distanceSquared( self.origin, self.node.origin ) > 16 * 16 )
|
||||
return false;
|
||||
|
||||
node = self findshufflecovernode();
|
||||
|
||||
if ( isdefined( node ) && ( node != self.node ) && self useCoverNode( node ) )
|
||||
{
|
||||
self.shuffleMove = true;
|
||||
self.shuffleNode = node;
|
||||
self.didShuffleMove = true;
|
||||
|
||||
// give code a chance use new cover node
|
||||
wait 0.5;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
25
animscripts/cover_crouch.gsc
Normal file
25
animscripts/cover_crouch.gsc
Normal file
@ -0,0 +1,25 @@
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\Utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
// assert( !usingSidearm() );
|
||||
|
||||
self endon( "killanimscript" );
|
||||
|
||||
// [[ self.exception[ "cover_crouch" ] ]]();
|
||||
|
||||
animscripts\utility::initialize( "cover_crouch" );
|
||||
|
||||
self animscripts\cover_wall::cover_wall_think( "crouch" );
|
||||
}
|
||||
|
||||
end_script()
|
||||
{
|
||||
self.coverCrouchLean_aimmode = undefined;
|
||||
|
||||
animscripts\cover_behavior::end_script( "crouch" );
|
||||
}
|
53
animscripts/cover_left.gsc
Normal file
53
animscripts/cover_left.gsc
Normal file
@ -0,0 +1,53 @@
|
||||
#include maps\_utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
// (Note that animations called right are used with left corner nodes, and vice versa.)
|
||||
|
||||
main()
|
||||
{
|
||||
self.animArrayFuncs = [];
|
||||
self.animArrayFuncs[ "hiding" ][ "stand" ] = ::set_animarray_standing_left;
|
||||
self.animArrayFuncs[ "hiding" ][ "crouch" ] = ::set_animarray_crouching_left;
|
||||
|
||||
if ( IsDefined( self.customAnimFunc ) && IsDefined( self.customAnimFunc[ "cover_left" ] ) )
|
||||
{
|
||||
if ( IsDefined( self.customAnimFunc[ "cover_left" ][ "stand" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "hiding" ][ "stand" ] = self.customAnimFunc[ "cover_left" ][ "stand" ];
|
||||
}
|
||||
|
||||
if ( IsDefined( self.customAnimFunc[ "cover_left" ][ "crouch" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "hiding" ][ "crouch" ] = self.customAnimFunc[ "cover_left" ][ "crouch" ];
|
||||
}
|
||||
}
|
||||
|
||||
self endon( "killanimscript" );
|
||||
animscripts\utility::initialize( "cover_left" );
|
||||
|
||||
animscripts\corner::corner_think( "left", 90 );
|
||||
}
|
||||
|
||||
end_script()
|
||||
{
|
||||
animscripts\corner::end_script_corner();
|
||||
animscripts\cover_behavior::end_script( "left" );
|
||||
}
|
||||
|
||||
set_animarray_standing_left() /* void */
|
||||
{
|
||||
assert( IsDefined(anim.coverLeftStand) );
|
||||
self.hideYawOffset = 90;
|
||||
self.a.array = anim.coverLeftStand;
|
||||
}
|
||||
|
||||
|
||||
set_animarray_crouching_left()
|
||||
{
|
||||
assert( IsDefined(anim.coverLeftCrouch) );
|
||||
self.hideYawOffset = 90;
|
||||
self.a.array = anim.coverLeftCrouch;
|
||||
}
|
||||
|
360
animscripts/cover_prone.gsc
Normal file
360
animscripts/cover_prone.gsc
Normal file
@ -0,0 +1,360 @@
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\utility;
|
||||
#include animscripts\shared;
|
||||
#include common_scripts\utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
// TODO:
|
||||
// - figure out why aiming range is incorrect (aiming arc seems a bit off)
|
||||
|
||||
main()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
animscripts\utility::initialize( "cover_prone" );
|
||||
|
||||
// TODO: run cover crouch or exposed crouch
|
||||
if ( weaponClass( self.weapon ) == "rocketlauncher" )
|
||||
{
|
||||
animscripts\combat::main();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isDefined( self.a.arrivalType ) && self.a.arrivalType == "prone_saw" )
|
||||
{
|
||||
assert( isDefined( self.node.turretInfo ) );
|
||||
self animscripts\cover_wall::useSelfPlacedTurret( "saw_bipod_prone", "weapon_saw_MG_Setup" );
|
||||
}
|
||||
else if ( isDefined( self.node.turret ) )
|
||||
{
|
||||
self animscripts\cover_wall::useStationaryTurret();
|
||||
}
|
||||
|
||||
// if we're too close to our enemy, stand up
|
||||
// (285 happens to be the same distance at which we leave cover and go into exposed if our enemy approaches)
|
||||
if ( isDefined( self.enemy ) && lengthSquared( self.origin - self.enemy.origin ) < squared( 512 ) )
|
||||
{
|
||||
self thread animscripts\combat::main();
|
||||
return;
|
||||
}
|
||||
|
||||
self setup_cover_prone();
|
||||
|
||||
self.coverNode = self.node;
|
||||
self OrientMode( "face angle", self.coverNode.angles[ 1 ] );
|
||||
|
||||
self.a.goingToProneAim = true;
|
||||
self setProneAnimNodes( -45, 45, %prone_legs_down, %exposed_modern, %prone_legs_up );
|
||||
if ( self.a.pose != "prone" )
|
||||
self prone_transitionTo( "prone" );
|
||||
else
|
||||
self EnterProneWrapper( 0 );
|
||||
|
||||
self thread aimIdleThread();
|
||||
|
||||
setupProneAim( 0.2 );
|
||||
self setAnim( %prone_aim_5, 1, 0.1 );
|
||||
|
||||
// face the direction of our covernode
|
||||
self OrientMode( "face angle", self.coverNode.angles[ 1 ] );
|
||||
self animmode( "zonly_physics" );
|
||||
|
||||
self proneCombatMainLoop();
|
||||
|
||||
self notify( "stop_deciding_how_to_shoot" );
|
||||
|
||||
}
|
||||
|
||||
end_script()
|
||||
{
|
||||
self.a.goingToProneAim = undefined;
|
||||
}
|
||||
|
||||
idleThread()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "kill_idle_thread" );
|
||||
for ( ;; )
|
||||
{
|
||||
idleAnim = animArrayPickRandom( "prone_idle" );
|
||||
self setflaggedanimlimited( "idle", idleAnim );
|
||||
self waittillmatch( "idle", "end" );
|
||||
self clearanim( idleAnim, .2 );
|
||||
}
|
||||
}
|
||||
|
||||
UpdateProneWrapper( time )
|
||||
{
|
||||
self UpdateProne( %prone_aim_feet_45up, %prone_aim_feet_45down, 1, time, 1 );
|
||||
self setanim( %exposed_aiming, 1, .2 );
|
||||
}
|
||||
|
||||
proneCombatMainLoop()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self thread trackShootEntOrPos();
|
||||
|
||||
// self thread ReacquireWhenNecessary();
|
||||
|
||||
self thread animscripts\shoot_behavior::decideWhatAndHowToShoot( "normal" );
|
||||
|
||||
// self resetGiveUpOnEnemyTime();
|
||||
|
||||
desynched = ( gettime() > 2500 );
|
||||
|
||||
//prof_begin("prone_combat");
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self animscripts\utility::IsInCombat();// reset our in - combat state
|
||||
|
||||
self UpdateProneWrapper( 0.05 );
|
||||
|
||||
if ( !desynched )
|
||||
{
|
||||
wait( 0.05 + randomfloat( 1.5 ) );
|
||||
desynched = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !isdefined( self.shootPos ) )
|
||||
{
|
||||
assert( !isdefined( self.shootEnt ) );
|
||||
if ( considerThrowGrenade() )
|
||||
continue;
|
||||
|
||||
wait( 0.05 );
|
||||
continue;
|
||||
}
|
||||
|
||||
assert( isdefined( self.shootPos ) );// we can use self.shootPos after this point.
|
||||
// self resetGiveUpOnEnemyTime();
|
||||
|
||||
// if we're too close to our enemy, stand up
|
||||
// (285 happens to be the same distance at which we leave cover and go into exposed if our enemy approaches)
|
||||
distSqToShootPos = lengthsquared( self.origin - self.shootPos );
|
||||
|
||||
if ( self.a.pose != "crouch" && self isStanceAllowed( "crouch" ) && distSqToShootPos < squared( 400 ) )
|
||||
{
|
||||
if ( distSqToShootPos < squared( 285 ) )
|
||||
{
|
||||
prone_transitionTo( "crouch" );
|
||||
self thread animscripts\combat::main();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ( considerThrowGrenade() )// TODO: make considerThrowGrenade work with shootPos rather than only self.enemy
|
||||
continue;
|
||||
|
||||
if ( self proneReload( 0 ) )
|
||||
continue;
|
||||
|
||||
if ( aimedAtShootEntOrPos() )
|
||||
{
|
||||
shootUntilShootBehaviorChange();
|
||||
self clearAnim( %add_fire, .2 );
|
||||
continue;
|
||||
}
|
||||
|
||||
// idleThread() is running, so just waiting a bit will cause us to idle
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
//prof_end("prone_combat");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
proneReload( threshold )
|
||||
{
|
||||
return Reload( threshold, self animArray( "reload" ) );
|
||||
}
|
||||
|
||||
|
||||
setup_cover_prone()
|
||||
{
|
||||
self setDefaultAimLimits( self.node );
|
||||
|
||||
anim_array = [];
|
||||
|
||||
anim_array[ "straight_level" ] = %prone_aim_5;
|
||||
|
||||
anim_array[ "fire" ] = %prone_fire_1;
|
||||
anim_array[ "semi2" ] = %prone_fire_burst;
|
||||
anim_array[ "semi3" ] = %prone_fire_burst;
|
||||
anim_array[ "semi4" ] = %prone_fire_burst;
|
||||
anim_array[ "semi5" ] = %prone_fire_burst;
|
||||
|
||||
anim_array[ "single" ] = array( %prone_fire_1 );
|
||||
anim_array[ "continuous" ] = array( %nx_tp_stand_exposed_stream_01 );
|
||||
|
||||
anim_array[ "burst2" ] = %prone_fire_burst;// ( will be limited to 2 shots )
|
||||
anim_array[ "burst3" ] = %prone_fire_burst;
|
||||
anim_array[ "burst4" ] = %prone_fire_burst;
|
||||
anim_array[ "burst5" ] = %prone_fire_burst;
|
||||
anim_array[ "burst6" ] = %prone_fire_burst;
|
||||
|
||||
anim_array[ "reload" ] = %prone_reload;
|
||||
|
||||
anim_array[ "look" ] = array( %prone_twitch_look, %prone_twitch_lookfast, %prone_twitch_lookup );
|
||||
|
||||
anim_array[ "grenade_safe" ] = array( %prone_grenade_A, %prone_grenade_A );
|
||||
anim_array[ "grenade_exposed" ] = array( %prone_grenade_A, %prone_grenade_A );
|
||||
|
||||
anim_array[ "exposed_idle" ] = array( %prone_idle );
|
||||
|
||||
anim_array[ "hide_to_look" ] = %coverstand_look_moveup;
|
||||
anim_array[ "look_idle" ] = %coverstand_look_idle;
|
||||
anim_array[ "look_to_hide" ] = %coverstand_look_movedown;
|
||||
anim_array[ "look_to_hide_fast" ] = %coverstand_look_movedown_fast;
|
||||
|
||||
anim_array[ "stand_2_prone" ] = %stand_2_prone_nodelta;
|
||||
anim_array[ "crouch_2_prone" ] = %crouch_2_prone;
|
||||
anim_array[ "prone_2_stand" ] = %prone_2_stand_nodelta;
|
||||
anim_array[ "prone_2_crouch" ] = %prone_2_crouch;
|
||||
anim_array[ "stand_2_prone_firing" ] = %stand_2_prone_firing;
|
||||
anim_array[ "crouch_2_prone_firing" ] = %crouch_2_prone_firing;
|
||||
anim_array[ "prone_2_stand_firing" ] = %prone_2_stand_firing;
|
||||
anim_array[ "prone_2_crouch_firing" ] = %prone_2_crouch_firing;
|
||||
|
||||
self.a.array = anim_array;
|
||||
}
|
||||
|
||||
|
||||
tryThrowingGrenade( throwAt, safe )
|
||||
{
|
||||
theanim = undefined;
|
||||
if ( isdefined( safe ) && safe )
|
||||
theanim = animArrayPickRandom( "grenade_safe" );
|
||||
else
|
||||
theanim = animArrayPickRandom( "grenade_exposed" );
|
||||
|
||||
self animMode( "zonly_physics" );// Unlatch the feet
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
armOffset = ( 32, 20, 64 );// needs fixing!
|
||||
threwGrenade = TryGrenade( throwAt, theanim );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
return threwGrenade;
|
||||
}
|
||||
|
||||
|
||||
considerThrowGrenade()
|
||||
{
|
||||
if ( isdefined( anim.throwGrenadeAtPlayerASAP ) && isAlive( level._player ) )
|
||||
{
|
||||
if ( tryThrowingGrenade( level._player, 200 ) )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( isdefined( self.enemy ) )
|
||||
return tryThrowingGrenade( self.enemy, 850 );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
shouldFireWhileChangingPose()
|
||||
{
|
||||
if ( !isdefined( self.weapon ) || !WeaponIsAuto( self.weapon ) )
|
||||
return false;
|
||||
|
||||
if ( isdefined( self.node ) && distanceSquared( self.origin, self.node.origin ) < 16 * 16 )
|
||||
return false;// we're on a node and can't use an animation with a delta
|
||||
if ( isDefined( self.enemy ) && self canSee( self.enemy ) && !isdefined( self.grenade ) && self getAimYawToShootEntOrPos() < 20 )
|
||||
return animscripts\move::MayShootWhileMoving();
|
||||
return false;
|
||||
}
|
||||
|
||||
prone_transitionTo( newPose )
|
||||
{
|
||||
if ( newPose == self.a.pose )
|
||||
return;
|
||||
|
||||
self clearanim( %root, .3 );
|
||||
|
||||
self endFireAndAnimIdleThread();
|
||||
|
||||
if ( shouldFireWhileChangingPose() )
|
||||
transAnim = animArray( self.a.pose + "_2_" + newPose + "_firing" );
|
||||
else
|
||||
transAnim = animArray( self.a.pose + "_2_" + newPose );
|
||||
|
||||
if ( newPose == "prone" )
|
||||
{
|
||||
// this is crucial. if it doesn't have this notetrack, we won't call enterProneWrapper!
|
||||
assert( animHasNotetrack( transAnim, "anim_pose = \"prone\"" ) );
|
||||
}
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "trans", transAnim, %body, 1, .2, 1.0 );
|
||||
animscripts\shared::DoNoteTracks( "trans" );
|
||||
|
||||
assert( self.a.pose == newPose );
|
||||
|
||||
self setAnimKnobAllRestart( animarray( "straight_level" ), %body, 1, .25 );
|
||||
setupProneAim( .25 );
|
||||
}
|
||||
|
||||
finishNoteTracks( animname )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
animscripts\shared::DoNoteTracks( animname );
|
||||
}
|
||||
|
||||
|
||||
setupProneAim( transTime )
|
||||
{
|
||||
self setAnimKnobAll( %prone_aim_5, %body, 1, transTime );
|
||||
self setAnimLimited( %prone_aim_2_add, 1, transTime );
|
||||
self setAnimLimited( %prone_aim_4_add, 1, transTime );
|
||||
self setAnimLimited( %prone_aim_6_add, 1, transTime );
|
||||
self setAnimLimited( %prone_aim_8_add, 1, transTime );
|
||||
}
|
||||
|
||||
|
||||
proneTo( newPose, rate )
|
||||
{
|
||||
assert( self.a.pose == "prone" );
|
||||
|
||||
// self OrientMode( "face angle", self.angles[1] );
|
||||
self clearanim( %root, .3 );
|
||||
|
||||
transAnim = undefined;
|
||||
|
||||
if ( shouldFireWhileChangingPose() )
|
||||
{
|
||||
if ( newPose == "crouch" )
|
||||
transAnim = %prone_2_crouch_firing;
|
||||
else if ( newPose == "stand" )
|
||||
transAnim = %prone_2_stand_firing;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( newPose == "crouch" )
|
||||
transAnim = %prone_2_crouch;
|
||||
else if ( newPose == "stand" )
|
||||
transAnim = %prone_2_stand_nodelta;
|
||||
}
|
||||
|
||||
if ( isdefined( self.prone_anim_override ) )
|
||||
transAnim = self.prone_anim_override;
|
||||
if ( isdefined( self.prone_rate_override ) )
|
||||
rate = self.prone_rate_override;
|
||||
|
||||
assert( isDefined( transAnim ) );
|
||||
|
||||
if ( !isdefined( rate ) )
|
||||
rate = 1;
|
||||
|
||||
self ExitProneWrapper( getAnimLength( transAnim ) / 2 );
|
||||
self setFlaggedAnimKnobAllRestart( "trans", transAnim, %body, 1, .2, rate );
|
||||
animscripts\shared::DoNoteTracks( "trans" );
|
||||
|
||||
self clearAnim( transAnim, 0.1 );
|
||||
|
||||
assert( self.a.pose == newPose );
|
||||
// self.a.pose = newPose; // failsafe
|
||||
}
|
53
animscripts/cover_right.gsc
Normal file
53
animscripts/cover_right.gsc
Normal file
@ -0,0 +1,53 @@
|
||||
#include maps\_utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
// (Note that animations called left are used with right corner nodes, and vice versa.)
|
||||
|
||||
main()
|
||||
{
|
||||
self.animArrayFuncs = [];
|
||||
self.animArrayFuncs[ "hiding" ][ "stand" ] = ::set_animarray_standing_right;
|
||||
self.animArrayFuncs[ "hiding" ][ "crouch" ] = ::set_animarray_crouching_right;
|
||||
|
||||
if ( IsDefined( self.customAnimFunc ) && IsDefined( self.customAnimFunc[ "cover_right" ] ) )
|
||||
{
|
||||
if ( IsDefined( self.customAnimFunc[ "cover_right" ][ "stand" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "hiding" ][ "stand" ] = self.customAnimFunc[ "cover_right" ][ "stand" ];
|
||||
}
|
||||
if ( IsDefined( self.customAnimFunc[ "cover_right" ][ "crouch" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "hiding" ][ "crouch" ] = self.customAnimFunc[ "cover_right" ][ "crouch" ];
|
||||
}
|
||||
}
|
||||
|
||||
self endon( "killanimscript" );
|
||||
animscripts\utility::initialize( "cover_right" );
|
||||
|
||||
animscripts\corner::corner_think( "right", -90 );
|
||||
}
|
||||
|
||||
end_script()
|
||||
{
|
||||
animscripts\corner::end_script_corner();
|
||||
animscripts\cover_behavior::end_script( "right" );
|
||||
}
|
||||
|
||||
|
||||
set_animarray_standing_right() /* void */
|
||||
{
|
||||
assert( IsDefined(anim.coverRightStand));
|
||||
self.hideYawOffset = -90;
|
||||
self.a.array = anim.coverRightStand;
|
||||
}
|
||||
|
||||
set_animarray_crouching_right()
|
||||
{
|
||||
assert( IsDefined(anim.coverRightCrouch));
|
||||
self.hideYawOffset = -90;
|
||||
self.a.array = anim.coverRightCrouch;
|
||||
}
|
||||
|
||||
|
22
animscripts/cover_stand.gsc
Normal file
22
animscripts/cover_stand.gsc
Normal file
@ -0,0 +1,22 @@
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\Utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// assert( !usingSidearm() );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
// [[ self.exception[ "cover_stand" ] ]]();
|
||||
|
||||
animscripts\utility::initialize( "cover_stand" );
|
||||
|
||||
self animscripts\cover_wall::cover_wall_think( "stand" );
|
||||
}
|
||||
|
||||
|
||||
end_script()
|
||||
{
|
||||
animscripts\cover_behavior::end_script( "stand" );
|
||||
}
|
893
animscripts/cover_wall.gsc
Normal file
893
animscripts/cover_wall.gsc
Normal file
@ -0,0 +1,893 @@
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\Utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
cover_wall_think( coverType )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
if ( isdefined( self.locked_combat ) && self.locked_combat )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.coverNode = self.node;
|
||||
self.coverType = coverType;
|
||||
|
||||
if ( !isDefined( self.node.turret ) )
|
||||
animscripts\cover_behavior::turnToMatchNodeDirection( 0 );
|
||||
|
||||
if ( coverType == "crouch" )
|
||||
{
|
||||
self setup_cover_crouch( "unknown" );
|
||||
self.coverNode initCoverCrouchNode();
|
||||
}
|
||||
else
|
||||
{
|
||||
self setup_cover_stand( "unknown" );
|
||||
}
|
||||
|
||||
self.a.aimIdleThread = undefined;
|
||||
|
||||
// face the direction of our covernode
|
||||
self OrientMode( "face angle", self.coverNode.angles[ 1 ] );
|
||||
|
||||
if ( isDefined( self.weapon ) && usingMG() && isDefined( self.node ) && isDefined( self.node.turretInfo ) && canspawnturret() )
|
||||
{
|
||||
if ( coverType == "crouch" )
|
||||
{
|
||||
if ( isRPD( self.weapon ) )
|
||||
weaponInfo = "rpd_bipod_crouch";
|
||||
else
|
||||
weaponInfo = "saw_bipod_crouch";
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isRPD( self.weapon ) )
|
||||
weaponInfo = "rpd_bipod_stand";
|
||||
else
|
||||
weaponInfo = "saw_bipod_stand";
|
||||
}
|
||||
|
||||
if ( isRPD( self.weapon ) )
|
||||
weaponModel = "weapon_rpd_MG_Setup";
|
||||
else
|
||||
weaponModel = "weapon_saw_MG_Setup";
|
||||
|
||||
self useSelfPlacedTurret( weaponInfo, weaponModel );
|
||||
}
|
||||
else if ( isDefined( self.node ) && isDefined( self.node.turret ) )
|
||||
{
|
||||
self useStationaryTurret();
|
||||
}
|
||||
|
||||
self animmode( "normal" );
|
||||
|
||||
//start in hide position
|
||||
if ( coverType == "crouch" && self.a.pose == "stand" )
|
||||
{
|
||||
transAnim = animArray( "stand_2_hide" );
|
||||
time = getAnimLength( transAnim );
|
||||
self setAnimKnobAllRestart( transAnim, %body, 1, 0.2, fasterAnimSpeed() );
|
||||
self thread animscripts\shared::moveToOriginOverTime( self.coverNode.origin, time );
|
||||
wait time;
|
||||
self.a.coverMode = "hide";
|
||||
}
|
||||
else
|
||||
{
|
||||
loopHide( .4 );// need to transition to hide here in case we didn't do an approach
|
||||
|
||||
if ( distanceSquared( self.origin, self.coverNode.origin ) > 1 )
|
||||
{
|
||||
self thread animscripts\shared::moveToOriginOverTime( self.coverNode.origin, .4 );
|
||||
wait( .2 );
|
||||
if ( coverType == "crouch" )
|
||||
self.a.pose = "crouch";
|
||||
wait( .2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
self animmode( "zonly_physics" );
|
||||
|
||||
if ( coverType == "crouch" )
|
||||
{
|
||||
if ( self.a.pose == "prone" )
|
||||
self ExitProneWrapper( 1 );
|
||||
self.a.pose = "crouch";// in case we only lerped into the pose
|
||||
}
|
||||
|
||||
if ( self.coverType == "stand" )
|
||||
self.a.special = "cover_stand";
|
||||
else
|
||||
self.a.special = "cover_crouch";
|
||||
|
||||
behaviorCallbacks = spawnstruct();
|
||||
if ( !self.fixedNode )
|
||||
behaviorCallbacks.moveToNearByCover = animscripts\cover_behavior::moveToNearbyCover;
|
||||
|
||||
behaviorCallbacks.reload = ::coverReload;
|
||||
behaviorCallbacks.leaveCoverAndShoot = ::popUpAndShoot;
|
||||
behaviorCallbacks.look = ::look;
|
||||
behaviorCallbacks.fastlook = ::fastLook;
|
||||
behaviorCallbacks.idle = ::idle;
|
||||
behaviorCallbacks.flinch = ::flinch;
|
||||
behaviorCallbacks.grenade = ::tryThrowingGrenade;
|
||||
behaviorCallbacks.grenadehidden = ::tryThrowingGrenadeStayHidden;
|
||||
behaviorCallbacks.blindfire = ::blindfire;
|
||||
|
||||
animscripts\cover_behavior::main( behaviorCallbacks );
|
||||
}
|
||||
|
||||
isRPD( weapon )
|
||||
{
|
||||
return getSubStr( weapon, 0, 3 ) == "rpd" && (weapon.size == 3 || weapon[3] == "_");
|
||||
}
|
||||
|
||||
initCoverCrouchNode()
|
||||
{
|
||||
if ( isdefined( self.crouchingIsOK ) )
|
||||
return;
|
||||
|
||||
// it's only ok to crouch at this node if we can see out from a crouched position.
|
||||
crouchHeightOffset = ( 0, 0, 42 );
|
||||
forward = anglesToForward( self.angles );
|
||||
self.crouchingIsOK = sightTracePassed( self.origin + crouchHeightOffset, self.origin + crouchHeightOffset + vector_multiply( forward, 64 ), false, undefined );
|
||||
}
|
||||
|
||||
|
||||
setup_cover_crouch( exposedAnimSet )
|
||||
{
|
||||
if ( !isdefined( self.locked_combat ) )
|
||||
{
|
||||
self setDefaultAimLimits( self.coverNode );
|
||||
}
|
||||
|
||||
self setup_crouching_anim_array( exposedAnimSet );
|
||||
}
|
||||
|
||||
|
||||
setup_cover_stand( exposedAnimSet )
|
||||
{
|
||||
if ( !isdefined( self.locked_combat ) )
|
||||
{
|
||||
self setDefaultAimLimits( self.coverNode );
|
||||
}
|
||||
|
||||
self setup_standing_anim_array( exposedAnimSet );
|
||||
}
|
||||
|
||||
|
||||
coverReload()
|
||||
{
|
||||
return Reload( 2.0, animArray( "reload" ) );// ( reload no matter what )
|
||||
}
|
||||
|
||||
|
||||
popUpAndShoot()
|
||||
{
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
if ( isdefined( self.ramboChance ) && randomFloat( 1 ) < self.ramboChance )
|
||||
{
|
||||
if ( rambo() )
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( !pop_up() )
|
||||
return false;
|
||||
|
||||
shootAsTold();
|
||||
|
||||
self endFireAndAnimIdleThread();
|
||||
|
||||
if ( isDefined( self.shootPos ) )
|
||||
{
|
||||
distSqToShootPos = lengthsquared( self.origin - self.shootPos );
|
||||
// too close for RPG or out of ammo
|
||||
if ( usingRocketLauncher() && ( distSqToShootPos < squared( 512 ) || self.a.rockets < 1 ) )
|
||||
{
|
||||
if ( self.a.pose == "stand" )
|
||||
animscripts\shared::throwDownWeapon( %RPG_stand_throw );
|
||||
else
|
||||
animscripts\shared::throwDownWeapon( %RPG_crouch_throw );
|
||||
}
|
||||
}
|
||||
|
||||
go_to_hide();
|
||||
|
||||
self.coverCrouchLean_aimmode = undefined;
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
shootAsTold()
|
||||
{
|
||||
self endon( "return_to_cover" );
|
||||
|
||||
self maps\_gameskill::didSomethingOtherThanShooting();
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( isdefined( self.shouldReturnToCover ) )
|
||||
break;
|
||||
|
||||
if ( !isdefined( self.shootPos ) ) {
|
||||
assert( !isdefined( self.shootEnt ) );
|
||||
// give shoot_behavior a chance to iterate
|
||||
self waittill( "do_slow_things" );
|
||||
waittillframeend;
|
||||
if ( isdefined( self.shootPos ) )
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !self.bulletsInClip )
|
||||
break;
|
||||
|
||||
// crouch only
|
||||
if ( self.coverType == "crouch" && needToChangeCoverMode() )
|
||||
{
|
||||
break;
|
||||
|
||||
// TODO: if changing between stances without returning to cover is implemented,
|
||||
// we can't just endon("return_to_cover") because it will cause problems when it
|
||||
// happens while changing stance.
|
||||
// see corner's implementation of this idea for a better implementation.
|
||||
|
||||
// NYI
|
||||
/*changeCoverMode();
|
||||
|
||||
// if they're moving too fast for us to respond intelligently to them,
|
||||
// give up on firing at them for the moment
|
||||
if ( needToChangeCoverMode() )
|
||||
break;
|
||||
|
||||
continue;*/
|
||||
}
|
||||
|
||||
shootUntilShootBehaviorChange_coverWall();
|
||||
self clearAnim( %add_fire, .2 );
|
||||
}
|
||||
}
|
||||
|
||||
shootUntilShootBehaviorChange_coverWall()
|
||||
{
|
||||
if ( self.coverType == "crouch" )
|
||||
self thread angleRangeThread();// gives stopShooting notify when shootPosOutsideLegalYawRange returns true
|
||||
self thread aimIdleThread();
|
||||
|
||||
shootUntilShootBehaviorChange();
|
||||
}
|
||||
|
||||
|
||||
rambo()
|
||||
{
|
||||
if ( !hasEnemySightPos() )
|
||||
return false;
|
||||
|
||||
animType = "rambo";
|
||||
if ( randomint( 10 ) < 2 )
|
||||
animType = "rambo_fail";
|
||||
|
||||
if ( !animArrayAnyExist( animType ) )
|
||||
return false;
|
||||
|
||||
if ( self.coverType == "crouch" && !self.coverNode.crouchingIsOK )
|
||||
return false;
|
||||
|
||||
pitch = getShootPosPitch( self.coverNode.origin + getNodeOffset( self.coverNode ) );
|
||||
if ( pitch > 15 )
|
||||
return false;
|
||||
|
||||
forward = anglesToForward( self.angles );
|
||||
stepto = self.origin + vector_multiply( forward, -16 );
|
||||
|
||||
if ( !self mayMoveToPoint( stepto ) )
|
||||
return false;
|
||||
|
||||
self.coverPosEstablishedTime = gettime();
|
||||
|
||||
self animMode( "zonly_physics" );
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
self.isRambo = true;
|
||||
self.a.prevAttack = "rambo";
|
||||
|
||||
self.changingCoverPos = true;
|
||||
|
||||
self thread animscripts\shared::ramboAim( 0 );
|
||||
|
||||
ramboAnim = animArrayPickRandom( animType );
|
||||
self setFlaggedAnimKnobAllRestart( "rambo", ramboAnim, %body, 1, .2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "rambo" );
|
||||
|
||||
self notify( "rambo_aim_end" );
|
||||
|
||||
self.changingCoverPos = false;
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
self.lastRamboTime = getTime();
|
||||
|
||||
self.changingCoverPos = false;
|
||||
self.isRambo = undefined;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
idle()
|
||||
{
|
||||
self endon( "end_idle" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
useTwitch = ( randomint( 2 ) == 0 && animArrayAnyExist( "hide_idle_twitch" ) );
|
||||
if ( useTwitch )
|
||||
idleanim = animArrayPickRandom( "hide_idle_twitch" );
|
||||
else
|
||||
idleanim = animarray( "hide_idle" );
|
||||
|
||||
playIdleAnimation( idleAnim, useTwitch );
|
||||
}
|
||||
}
|
||||
|
||||
flinch()
|
||||
{
|
||||
if ( !animArrayAnyExist( "hide_idle_flinch" ) )
|
||||
return false;
|
||||
|
||||
forward = anglesToForward( self.angles );
|
||||
stepto = self.origin + vector_multiply( forward, -16 );
|
||||
|
||||
if ( !self mayMoveToPoint( stepto ) )
|
||||
return false;
|
||||
|
||||
self animmode( "zonly_physics" );
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
flinchanim = animArrayPickRandom( "hide_idle_flinch" );
|
||||
playIdleAnimation( flinchanim, true );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
playIdleAnimation( idleAnim, needsRestart )
|
||||
{
|
||||
if ( needsRestart )
|
||||
self setFlaggedAnimKnobAllRestart( "idle", idleAnim, %body, 1, 0.25, 1 );
|
||||
else
|
||||
self setFlaggedAnimKnobAll( "idle", idleAnim, %body, 1, 0.25, 1 );
|
||||
|
||||
self.a.coverMode = "hide";
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "idle" );
|
||||
}
|
||||
|
||||
look( lookTime )
|
||||
{
|
||||
if ( !isdefined( self.a.array[ "hide_to_look" ] ) )
|
||||
return false;
|
||||
|
||||
if ( !peekOut() )
|
||||
return false;
|
||||
|
||||
animscripts\shared::playLookAnimation( animArray( "look_idle" ), lookTime );// TODO: replace
|
||||
|
||||
lookanim = undefined;
|
||||
if ( self isSuppressedWrapper() )
|
||||
lookanim = animArray( "look_to_hide_fast" );
|
||||
else
|
||||
lookanim = animArray( "look_to_hide" );
|
||||
|
||||
self setflaggedanimknoballrestart( "looking_end", lookanim, %body, 1, .1 );
|
||||
animscripts\shared::DoNoteTracks( "looking_end" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
peekOut()
|
||||
{
|
||||
if ( isdefined( self.coverNode.script_dontpeek ) )
|
||||
return false;
|
||||
|
||||
// assuming no delta, so no maymovetopoint check
|
||||
|
||||
self setFlaggedAnimKnobAll( "looking_start", animArray( "hide_to_look" ), %body, 1, .2 );
|
||||
animscripts\shared::DoNoteTracks( "looking_start" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
fastLook()
|
||||
{
|
||||
self setFlaggedAnimKnobAllRestart( "look", animArrayPickRandom( "look" ), %body, 1, .1 );
|
||||
self animscripts\shared::DoNoteTracks( "look" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// These should be adjusted in animation data
|
||||
pop_up_and_hide_speed()
|
||||
{
|
||||
if ( self.a.coverMode == "left" || self.a.coverMode == "right" || self.a.coverMode == "over" )
|
||||
return 1;
|
||||
|
||||
return randomfasterAnimSpeed();
|
||||
}
|
||||
|
||||
|
||||
pop_up()
|
||||
{
|
||||
assert( !isdefined( self.a.coverMode ) || self.a.coverMode == "hide" );
|
||||
|
||||
newCoverMode = getBestCoverMode();
|
||||
|
||||
timeleft = .1;
|
||||
|
||||
popupAnim = animArray( "hide_2_" + newCoverMode );
|
||||
|
||||
if ( !self mayMoveToPoint( getAnimEndPos( popupAnim ) ) )
|
||||
return false;
|
||||
|
||||
if ( self.script == "cover_crouch" && newCoverMode == "lean" )
|
||||
self.coverCrouchLean_aimmode = true;
|
||||
|
||||
if ( self.coverType == "crouch" )
|
||||
self setup_cover_crouch( newCoverMode );
|
||||
else
|
||||
self setup_cover_stand( newCoverMode );
|
||||
|
||||
self.a.special = "none";
|
||||
self.specialDeathFunc = undefined;
|
||||
|
||||
if ( self.coverType == "stand" )
|
||||
self.a.special = "cover_stand_aim";
|
||||
else
|
||||
self.a.special = "cover_crouch_aim";
|
||||
|
||||
self.changingCoverPos = true;
|
||||
self notify( "done_changing_cover_pos" );
|
||||
|
||||
self animmode( "zonly_physics" );
|
||||
|
||||
animRate = pop_up_and_hide_speed();
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "pop_up", popUpAnim, %body, 1, .1, animRate );
|
||||
self thread DoNoteTracksForPopup( "pop_up" );
|
||||
|
||||
if ( animHasNoteTrack( popupAnim, "start_aim" ) )
|
||||
{
|
||||
self waittillmatch( "pop_up", "start_aim" );
|
||||
timeleft = getAnimLength( popupAnim ) / animRate * ( 1 - self getAnimTime( popupAnim ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
self waittillmatch( "pop_up", "end" );
|
||||
timeleft = .1;
|
||||
}
|
||||
|
||||
self clearAnim( popUpAnim, timeleft + 0.05 );
|
||||
|
||||
self.a.coverMode = newCoverMode;
|
||||
self.a.prevAttack = newCoverMode;
|
||||
self setup_additive_aim( timeleft );
|
||||
self thread animscripts\shared::trackShootEntOrPos();
|
||||
|
||||
wait( timeleft );
|
||||
|
||||
if ( self isSniper() )
|
||||
{
|
||||
thread animscripts\shoot_behavior::sniper_glint_behavior();
|
||||
}
|
||||
|
||||
self.changingCoverPos = false;
|
||||
self.coverPosEstablishedTime = gettime();
|
||||
|
||||
self notify( "stop_popup_donotetracks" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
DoNoteTracksForPopup( animname )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop_popup_donotetracks" );
|
||||
self animscripts\shared::DoNoteTracks( animname );
|
||||
}
|
||||
|
||||
|
||||
setup_additive_aim( transTime )
|
||||
{
|
||||
if ( self.a.coverMode == "left" || self.a.coverMode == "right" )
|
||||
aimCoverMode = "crouch";
|
||||
else
|
||||
aimCoverMode = self.a.coverMode;
|
||||
|
||||
self setAnimKnobAll( animArray( aimCoverMode + "_aim" ), %body, 1, transTime );
|
||||
if ( aimCoverMode == "crouch" )
|
||||
{
|
||||
self setanimlimited( %covercrouch_aim2_add, 1, 0 );
|
||||
self setanimlimited( %covercrouch_aim4_add, 1, 0 );
|
||||
self setanimlimited( %covercrouch_aim6_add, 1, 0 );
|
||||
self setanimlimited( %covercrouch_aim8_add, 1, 0 );
|
||||
}
|
||||
else if ( aimCoverMode == "stand" )
|
||||
{
|
||||
self setanimlimited( %exposed_aim_2, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_4, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_6, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_8, 1, 0 );
|
||||
}
|
||||
else if ( aimCoverMode == "lean" )
|
||||
{
|
||||
self setanimlimited( %exposed_aim_2, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_4, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_6, 1, 0 );
|
||||
self setanimlimited( %exposed_aim_8, 1, 0 );
|
||||
// these don't seem to have 45 degree aiming limits,
|
||||
// so i'm using the exposed ones instead
|
||||
/*self setanimlimited(%covercrouch_lean_aim2_add,1,0);
|
||||
self setanimlimited(%covercrouch_lean_aim4_add,1,0);
|
||||
self setanimlimited(%covercrouch_lean_aim6_add,1,0);
|
||||
self setanimlimited(%covercrouch_lean_aim8_add,1,0);*/
|
||||
}
|
||||
else if ( aimCoverMode == "over" )
|
||||
{
|
||||
self setanimlimited( %coverstandaim_aim2_add, 1, 0 );
|
||||
self setanimlimited( %coverstandaim_aim4_add, 1, 0 );
|
||||
self setanimlimited( %coverstandaim_aim6_add, 1, 0 );
|
||||
self setanimlimited( %coverstandaim_aim8_add, 1, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
go_to_hide()
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
|
||||
self.changingCoverPos = true; self notify( "done_changing_cover_pos" );
|
||||
|
||||
self endAimIdleThread();
|
||||
|
||||
animRate = pop_up_and_hide_speed();
|
||||
|
||||
self setFlaggedAnimKnobAll( "go_to_hide", animArray( self.a.coverMode + "_2_hide" ), %body, 1, 0.2, animRate );
|
||||
self clearAnim( %exposed_modern, 0.2 );
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "go_to_hide" );
|
||||
|
||||
self.a.coverMode = "hide";
|
||||
|
||||
if ( self.coverType == "stand" )
|
||||
self.a.special = "cover_stand";
|
||||
else
|
||||
self.a.special = "cover_crouch";
|
||||
|
||||
self.changingCoverPos = false;
|
||||
}
|
||||
|
||||
|
||||
tryThrowingGrenadeStayHidden( throwAt )
|
||||
{
|
||||
// TODO: check suppression and add rambo grenade support
|
||||
return tryThrowingGrenade( throwAt, true );
|
||||
}
|
||||
|
||||
|
||||
tryThrowingGrenade( throwAt, safe )
|
||||
{
|
||||
if ( isdefined( self.dontEverShoot ) || isdefined( throwAt.dontAttackMe ) )
|
||||
return false;
|
||||
|
||||
theanim = undefined;
|
||||
if ( isdefined( self.ramboChance ) && randomfloat( 1.0 ) < self.ramboChance )
|
||||
{
|
||||
theanim = animArrayPickRandom( "grenade_rambo" );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isdefined( safe ) && safe )
|
||||
theanim = animArrayPickRandom( "grenade_safe" );
|
||||
else
|
||||
theanim = animArrayPickRandom( "grenade_exposed" );
|
||||
}
|
||||
|
||||
self animMode( "zonly_physics" );// Unlatch the feet
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
threwGrenade = TryGrenade( throwAt, theanim );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
return threwGrenade;
|
||||
}
|
||||
|
||||
|
||||
blindfire()
|
||||
{
|
||||
if ( !animArrayAnyExist( "blind_fire" ) )
|
||||
return false;
|
||||
|
||||
self animMode( "zonly_physics" );
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "blindfire", animArrayPickRandom( "blind_fire" ), %body, 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "blindfire" );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
createTurret( posEnt, weaponInfo, weaponModel )
|
||||
{
|
||||
turret = spawnTurret( "misc_turret", posEnt.origin, weaponInfo );
|
||||
turret.angles = posEnt.angles;
|
||||
turret.aiOwner = self;
|
||||
turret setModel( weaponModel );
|
||||
turret makeUsable();
|
||||
turret setDefaultDropPitch( 0 );
|
||||
|
||||
if ( isDefined( posEnt.leftArc ) )
|
||||
turret.leftArc = posEnt.leftArc;
|
||||
if ( isDefined( posEnt.rightArc ) )
|
||||
turret.rightArc = posEnt.rightArc;
|
||||
if ( isDefined( posEnt.topArc ) )
|
||||
turret.topArc = posEnt.topArc;
|
||||
if ( isDefined( posEnt.bottomArc ) )
|
||||
turret.bottomArc = posEnt.bottomArc;
|
||||
|
||||
return turret;
|
||||
}
|
||||
|
||||
deleteIfNotUsed( owner )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "being_used" );
|
||||
|
||||
wait .1;
|
||||
|
||||
if ( isdefined( owner ) )
|
||||
{
|
||||
assert( !isdefined( owner.a.usingTurret ) || owner.a.usingTurret != self );
|
||||
owner notify( "turret_use_failed" );
|
||||
}
|
||||
self delete();
|
||||
}
|
||||
|
||||
useSelfPlacedTurret( weaponInfo, weaponModel )
|
||||
{
|
||||
turret = self createTurret( self.node.turretInfo, weaponInfo, weaponModel );
|
||||
|
||||
if ( self useTurret( turret ) )
|
||||
{
|
||||
turret thread deleteIfNotUsed( self );
|
||||
if ( isdefined( self.turret_function ) )
|
||||
thread [[ self.turret_function ]]( turret );
|
||||
// self setAnimKnob( %cover, 0, 0 );
|
||||
self waittill( "turret_use_failed" );// generally this won't notify, and we'll just not do any more cover_wall for now
|
||||
}
|
||||
else
|
||||
{
|
||||
turret delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
useStationaryTurret()
|
||||
{
|
||||
assert( isdefined( self.node ) );
|
||||
assert( isdefined( self.node.turret ) );
|
||||
|
||||
turret = self.node.turret;
|
||||
if ( !turret.isSetup )
|
||||
return;
|
||||
|
||||
// turret setmode( "auto_ai" ); // auto, auto_ai, manual, manual_ai
|
||||
// turret startFiring(); // seems to be a bug with the turret being in manual mode to start with
|
||||
// wait( 1 );
|
||||
thread maps\_mg_penetration::gunner_think( turret );
|
||||
self waittill( "continue_cover_script" );
|
||||
|
||||
// turret thread maps\_spawner::restorePitch();
|
||||
// self useturret( turret ); // dude should be near the mg42
|
||||
}
|
||||
|
||||
get_standing_wall_cover_anim()
|
||||
{
|
||||
if ( IsDefined( self.customStandWallAnims ) )
|
||||
{
|
||||
return self.customStandWallAnims;
|
||||
}
|
||||
else
|
||||
{
|
||||
return anim.animsets.standWallAnimSet;
|
||||
}
|
||||
}
|
||||
|
||||
get_crouching_wall_cover_anim()
|
||||
{
|
||||
if ( IsDefined( self.customCrouchWallAnims ) )
|
||||
{
|
||||
return self.customCrouchWallAnims;
|
||||
}
|
||||
else
|
||||
{
|
||||
return anim.animsets.crouchWallAnimSet;
|
||||
}
|
||||
}
|
||||
|
||||
setup_crouching_anim_array( exposedAnimSet )
|
||||
{
|
||||
anim_array = get_crouching_wall_cover_anim();
|
||||
|
||||
if ( weapon_pump_action_shotgun() )
|
||||
{
|
||||
if ( exposedAnimSet == "lean" || exposedAnimSet == "stand" )
|
||||
anim_array[ "single" ] = anim_array[ "shotgun_lean_single" ];
|
||||
else
|
||||
anim_array[ "single" ] = anim_array[ "shotgun_over_single" ];
|
||||
}
|
||||
else
|
||||
{
|
||||
anim_array[ "single" ] = anim_array[ "normal_single" ];
|
||||
}
|
||||
|
||||
if ( isDefined( anim.ramboAnims ) )
|
||||
{
|
||||
anim_array[ "rambo" ] = anim.ramboAnims.covercrouch;
|
||||
anim_array[ "rambo_fail" ] = anim.ramboAnims.covercrouchfail;
|
||||
anim_array[ "grenade_rambo" ] = anim.ramboAnims.covercrouchgrenade;
|
||||
}
|
||||
|
||||
self.a.array = anim_array;
|
||||
}
|
||||
|
||||
|
||||
setup_standing_anim_array( exposedAnimSet )
|
||||
{
|
||||
anim_array = get_standing_wall_cover_anim();
|
||||
|
||||
if ( exposedAnimSet == "over" )
|
||||
{
|
||||
anim_array[ "fire" ] = anim_array[ "over_fire" ];
|
||||
anim_array[ "semi2" ] = anim_array[ "over_semi2" ];
|
||||
anim_array[ "semi3" ] = anim_array[ "over_semi3" ];
|
||||
anim_array[ "semi4" ] = anim_array[ "over_semi4" ];
|
||||
anim_array[ "semi5" ] = anim_array[ "over_semi5" ];
|
||||
|
||||
anim_array[ "single" ] = anim_array[ "over_single" ];
|
||||
|
||||
anim_array[ "burst2" ] = anim_array[ "over_burst2" ];
|
||||
anim_array[ "burst3" ] = anim_array[ "over_burst3" ];
|
||||
anim_array[ "burst4" ] = anim_array[ "over_burst4" ];
|
||||
anim_array[ "burst5" ] = anim_array[ "over_burst5" ];
|
||||
anim_array[ "burst6" ] = anim_array[ "over_burst6" ];
|
||||
|
||||
anim_array[ "continuous" ] = anim_array[ "over_continuous" ];
|
||||
}
|
||||
else
|
||||
{
|
||||
anim_array[ "fire" ] = anim_array[ "stand_fire" ];
|
||||
anim_array[ "semi2" ] = anim_array[ "stand_semi2" ];
|
||||
anim_array[ "semi3" ] = anim_array[ "stand_semi3" ];
|
||||
anim_array[ "semi4" ] = anim_array[ "stand_semi4" ];
|
||||
anim_array[ "semi5" ] = anim_array[ "stand_semi5" ];
|
||||
|
||||
if ( weapon_pump_action_shotgun() )
|
||||
anim_array[ "single" ] = anim_array[ "stand_shotgun_single" ];
|
||||
else
|
||||
anim_array[ "single" ] = anim_array[ "stand_normal_single" ];
|
||||
|
||||
anim_array[ "burst2" ] = anim_array[ "stand_burst2" ];
|
||||
anim_array[ "burst3" ] = anim_array[ "stand_burst3" ];
|
||||
anim_array[ "burst4" ] = anim_array[ "stand_burst4" ];
|
||||
anim_array[ "burst5" ] = anim_array[ "stand_burst5" ];
|
||||
anim_array[ "burst6" ] = anim_array[ "stand_burst6" ];
|
||||
|
||||
anim_array[ "continuous" ] = anim_array[ "stand_continuous" ];
|
||||
}
|
||||
|
||||
if ( isDefined( anim.ramboAnims ) )
|
||||
{
|
||||
anim_array[ "rambo" ] = anim.ramboAnims.coverstand;
|
||||
anim_array[ "rambo_fail" ] = anim.ramboAnims.coverstandfail;
|
||||
anim_array[ "grenade_rambo" ] = anim.ramboAnims.coverstandgrenade;
|
||||
}
|
||||
|
||||
self.a.array = anim_array;
|
||||
}
|
||||
|
||||
|
||||
loopHide( transTime )
|
||||
{
|
||||
if ( !isdefined( transTime ) )
|
||||
transTime = .1;
|
||||
|
||||
self setanimknoballrestart( animArray( "hide_idle" ), %body, 1, transTime );
|
||||
self.a.coverMode = "hide";
|
||||
}
|
||||
|
||||
|
||||
angleRangeThread()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self notify( "newAngleRangeCheck" );
|
||||
self endon( "newAngleRangeCheck" );
|
||||
self endon( "return_to_cover" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( needToChangeCoverMode() )
|
||||
break;
|
||||
wait( 0.1 );
|
||||
}
|
||||
|
||||
self notify( "stopShooting" );// For changing shooting pose to compensate for player moving
|
||||
}
|
||||
|
||||
|
||||
needToChangeCoverMode()
|
||||
{
|
||||
if ( self.coverType != "crouch" )
|
||||
return false;
|
||||
|
||||
pitch = getShootPosPitch( self getEye() );
|
||||
|
||||
if ( self.a.coverMode == "lean" )
|
||||
{
|
||||
return pitch < 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pitch > 45;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getBestCoverMode()
|
||||
{
|
||||
modes = [];
|
||||
assert( isdefined( self.coverNode ) );
|
||||
|
||||
if ( isdefined( self.get_valid_peekout_func ) )
|
||||
{
|
||||
modes = self.coverNode [[ self.get_valid_peekout_func ]]();
|
||||
}
|
||||
else if ( self.coverType == "stand" )
|
||||
{
|
||||
modes = self.coverNode GetValidCoverPeekOuts();
|
||||
modes[ modes.size ] = "stand";
|
||||
}
|
||||
else
|
||||
{
|
||||
pitch = getShootPosPitch( self.coverNode.origin + getNodeOffset( self.coverNode ) );
|
||||
|
||||
if ( pitch > 30 )
|
||||
return "lean";
|
||||
if ( pitch > 15 || !self.coverNode.crouchingIsOK )
|
||||
return "stand";
|
||||
|
||||
modes = self.coverNode GetValidCoverPeekOuts();
|
||||
modes[ modes.size ] = "crouch";
|
||||
}
|
||||
|
||||
return getRandomCoverMode( modes );
|
||||
}
|
||||
|
||||
|
||||
getShootPosPitch( fromPos )
|
||||
{
|
||||
shootPos = getEnemyEyePos();
|
||||
|
||||
return AngleClamp180( vectorToAngles( shootPos - fromPos )[ 0 ] );
|
||||
}
|
304
animscripts/cqb.gsc
Normal file
304
animscripts/cqb.gsc
Normal file
@ -0,0 +1,304 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\shared;
|
||||
#include common_scripts\utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
MoveCQB()
|
||||
{
|
||||
animscripts\run::changeWeaponStandRun();
|
||||
|
||||
// any endons in this function must also be in CQBShootWhileMoving and CQBDecideWhatAndHowToShoot
|
||||
|
||||
if ( self.a.pose != "stand" )
|
||||
{
|
||||
// (get rid of any prone or other stuff that might be going on)
|
||||
self clearAnim( %root, 0.2 );
|
||||
if ( self.a.pose == "prone" )
|
||||
self ExitProneWrapper( 1 );
|
||||
self.a.pose = "stand";
|
||||
}
|
||||
self.a.movement = self.moveMode;
|
||||
|
||||
//self clearanim(%combatrun, 0.2);
|
||||
|
||||
self thread CQBTracking();
|
||||
|
||||
cqbWalkAnim = DetermineCQBAnim();
|
||||
|
||||
rate = self.moveplaybackrate;
|
||||
|
||||
if ( self.moveMode == "walk" )
|
||||
rate *= 0.6;
|
||||
|
||||
transTime = get_cqb_blend_in_time();
|
||||
|
||||
// (we don't use %body because that would reset the aiming knobs)
|
||||
self setFlaggedAnimKnobAll( "runanim", cqbWalkAnim, %walk_and_run_loops, 1, transTime, rate, true );
|
||||
self set_move_anim_start_point();
|
||||
self animscripts\run::SetMoveNonForwardAnims( GetCQBAnim("move_b"), GetCQBAnim("move_l"), GetCQBAnim("move_r") );
|
||||
self thread animscripts\run::SetCombatStandMoveAnimWeights( "cqb" );
|
||||
|
||||
animscripts\shared::DoNoteTracksForTime( 0.2, "runanim" );
|
||||
|
||||
self thread animscripts\run::stopShootWhileMovingThreads();
|
||||
}
|
||||
|
||||
DetermineCQBAnim()
|
||||
{
|
||||
//TagCC<NOTE>: This is rather fail. the self.MoveMode that GetRunAnim uses is used to set the anim are always run
|
||||
//so effectively this line says that if a custom cqb animset is defined, don't use it, or even the normal cqb anims,
|
||||
//but instead use the run anim set. Great. No one noticed this bug because cqb isn't ever overridden where run isn't
|
||||
//also overriden to the same thing in mw2 (see riotshield).
|
||||
//if ( isdefined( self.customMoveAnimSet ) && isdefined( self.customMoveAnimSet[ "cqb" ] ) )
|
||||
// return animscripts\run::GetRunAnim();
|
||||
|
||||
if ( self.stairsState == "up" )
|
||||
{
|
||||
return GetCQBAnim( "stairs_up" );
|
||||
}
|
||||
|
||||
if ( self.stairsState == "down" )
|
||||
{
|
||||
return GetCQBAnim( "stairs_down" );
|
||||
}
|
||||
|
||||
if ( self.movemode == "walk" )
|
||||
{
|
||||
return GetCQBAnim( "move_f" );
|
||||
}
|
||||
|
||||
variation = getRandomIntFromSeed( self.a.runLoopCount, 2 );
|
||||
if ( variation == 0 )
|
||||
{
|
||||
return GetCQBAnim( "straight" );
|
||||
}
|
||||
|
||||
return GetCQBAnim( "straight_variation" );
|
||||
}
|
||||
|
||||
get_cqb_blend_in_time()
|
||||
{
|
||||
transTime = 0.1;
|
||||
if ( self.stairsState == "none" )
|
||||
{
|
||||
transTime = 0.3;
|
||||
//tagCC<NOTE>:for debugging, lets allow for this to be tweaked in script. remove at some point.
|
||||
if( self.subclass == "moon" )
|
||||
{
|
||||
transTime = 0.8;
|
||||
|
||||
if( IsDefined( self.cqb_blend_finish_time ) )
|
||||
{
|
||||
transTime = self.cqb_blend_finish_time;
|
||||
self.cqb_blend_finish_time = undefined;
|
||||
}
|
||||
|
||||
run_blend_str = GetDvar("scr_run_blend");
|
||||
if( run_blend_str != "" )
|
||||
{
|
||||
transTime = Float( run_blend_str );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
transTime = 0.1; // need to transition to stairs quickly
|
||||
}
|
||||
|
||||
return transTime;
|
||||
}
|
||||
|
||||
GetCQBAnim( anim_name )
|
||||
{
|
||||
if ( IsDefined( self.customMoveAnimSet ) && IsDefined( self.customMoveAnimSet[ "cqb" ] ) && IsDefined( self.customMoveAnimSet[ "cqb" ][anim_name] ) )
|
||||
{
|
||||
return self.customMoveAnimSet[ "cqb" ][ anim_name ];
|
||||
}
|
||||
else
|
||||
{
|
||||
return anim.animsets.move[ "cqb" ][ anim_name ];
|
||||
}
|
||||
}
|
||||
|
||||
CQBTracking()
|
||||
{
|
||||
assert( isdefined( self.aim_while_moving_thread ) == isdefined( self.trackLoopThread ) );
|
||||
assertex( !isdefined( self.trackLoopThread ) || (self.trackLoopThreadType == "faceEnemyAimTracking"), self.trackLoopThreadType );
|
||||
|
||||
if ( animscripts\move::MayShootWhileMoving() )
|
||||
animscripts\run::runShootWhileMovingThreads();
|
||||
|
||||
animscripts\run::faceEnemyAimTracking();
|
||||
}
|
||||
|
||||
setupCQBPointsOfInterest()
|
||||
{
|
||||
level._cqbPointsOfInterest = [];
|
||||
pointents = getEntArray( "cqb_point_of_interest", "targetname" );
|
||||
for ( i = 0; i < pointents.size; i++ )
|
||||
{
|
||||
level._cqbPointsOfInterest[ i ] = pointents[ i ].origin;
|
||||
pointents[ i ] delete();
|
||||
}
|
||||
}
|
||||
|
||||
findCQBPointsOfInterest()
|
||||
{
|
||||
if ( isdefined( anim.findingCQBPointsOfInterest ) )
|
||||
return;
|
||||
anim.findingCQBPointsOfInterest = true;
|
||||
|
||||
// one AI per frame, find best point of interest.
|
||||
if ( !level._cqbPointsOfInterest.size )
|
||||
return;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
ai = getaiarray();
|
||||
waited = false;
|
||||
foreach( guy in ai )
|
||||
{
|
||||
if ( isAlive( guy ) && guy isCQBWalking() )
|
||||
{
|
||||
moving = ( guy.a.movement != "stop" );
|
||||
|
||||
// if you change this, change the debug function below too
|
||||
|
||||
shootAtPos = (guy.origin[0], guy.origin[1], guy getShootAtPos()[2]);
|
||||
lookAheadPoint = shootAtPos;
|
||||
forward = anglesToForward( guy.angles );
|
||||
if ( moving )
|
||||
{
|
||||
trace = bulletTrace( lookAheadPoint, lookAheadPoint + forward * 128, false, undefined );
|
||||
lookAheadPoint = trace[ "position" ];
|
||||
}
|
||||
|
||||
best = -1;
|
||||
bestdist = 1024 * 1024;
|
||||
for ( j = 0; j < level._cqbPointsOfInterest.size; j++ )
|
||||
{
|
||||
point = level._cqbPointsOfInterest[ j ];
|
||||
|
||||
dist = distanceSquared( point, lookAheadPoint );
|
||||
if ( dist < bestdist )
|
||||
{
|
||||
if ( moving )
|
||||
{
|
||||
if ( distanceSquared( point, shootAtPos ) < 64 * 64 )
|
||||
continue;
|
||||
dot = vectorDot( vectorNormalize( point - shootAtPos ), forward );
|
||||
if ( dot < 0.643 || dot > 0.966 )// 0.643 = cos( 50 ), 0.966 = cos( 15 )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( dist < 50 * 50 )
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( !sightTracePassed( lookAheadPoint, point, false, undefined ) )
|
||||
continue;
|
||||
|
||||
bestdist = dist;
|
||||
best = j;
|
||||
}
|
||||
}
|
||||
|
||||
if ( best < 0 )
|
||||
guy.cqb_point_of_interest = undefined;
|
||||
else
|
||||
guy.cqb_point_of_interest = level._cqbPointsOfInterest[ best ];
|
||||
|
||||
wait .05;
|
||||
waited = true;
|
||||
}
|
||||
}
|
||||
if ( !waited )
|
||||
wait .25;
|
||||
}
|
||||
}
|
||||
|
||||
/#
|
||||
CQBDebug()
|
||||
{
|
||||
self notify( "end_cqb_debug" );
|
||||
self endon( "end_cqb_debug" );
|
||||
self endon( "death" );
|
||||
|
||||
setDvarIfUninitialized( "scr_cqbdebug", "off" );
|
||||
|
||||
level thread CQBDebugGlobal();
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( getdebugdvar( "scr_cqbdebug" ) == "on" || getdebugdvarint( "scr_cqbdebug" ) == self getentnum() )
|
||||
{
|
||||
shootAtPos = (self.origin[0], self.origin[1], self getShootAtPos()[2]);
|
||||
if ( isdefined( self.shootPos ) )
|
||||
{
|
||||
line( shootAtPos, self.shootPos, ( 1, 1, 1 ) );
|
||||
print3d( self.shootPos, "shootPos", ( 1, 1, 1 ), 1, 0.5 );
|
||||
}
|
||||
else if ( isdefined( self.cqb_target ) )
|
||||
{
|
||||
line( shootAtPos, self.cqb_target.origin, ( .5, 1, .5 ) );
|
||||
print3d( self.cqb_target.origin, "cqb_target", ( .5, 1, .5 ), 1, 0.5 );
|
||||
}
|
||||
else
|
||||
{
|
||||
moving = ( self.a.movement != "stop" );
|
||||
|
||||
forward = anglesToForward( self.angles );
|
||||
lookAheadPoint = shootAtPos;
|
||||
if ( moving )
|
||||
{
|
||||
lookAheadPoint += forward * 128;
|
||||
line( shootAtPos, lookAheadPoint, ( 0.7, .5, .5 ) );
|
||||
|
||||
right = anglesToRight( self.angles );
|
||||
leftScanArea = shootAtPos + ( forward * 0.643 - right ) * 64;
|
||||
rightScanArea = shootAtPos + ( forward * 0.643 + right ) * 64;
|
||||
line( shootAtPos, leftScanArea, ( 0.5, 0.5, 0.5 ), 0.7 );
|
||||
line( shootAtPos, rightScanArea, ( 0.5, 0.5, 0.5 ), 0.7 );
|
||||
}
|
||||
|
||||
if ( isdefined( self.cqb_point_of_interest ) )
|
||||
{
|
||||
line( lookAheadPoint, self.cqb_point_of_interest, ( 1, .5, .5 ) );
|
||||
print3d( self.cqb_point_of_interest, "cqb_point_of_interest", ( 1, .5, .5 ), 1, 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
wait .05;
|
||||
continue;
|
||||
}
|
||||
|
||||
wait 1;
|
||||
}
|
||||
}
|
||||
|
||||
CQBDebugGlobal()
|
||||
{
|
||||
if ( isdefined( level._cqbdebugglobal ) )
|
||||
return;
|
||||
level._cqbdebugglobal = true;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( getdebugdvar( "scr_cqbdebug" ) != "on" )
|
||||
{
|
||||
wait 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
for ( i = 0; i < level._cqbPointsOfInterest.size; i++ )
|
||||
{
|
||||
print3d( level._cqbPointsOfInterest[ i ], ".", ( .7, .7, 1 ), .7, 3 );
|
||||
}
|
||||
|
||||
wait .05;
|
||||
}
|
||||
}
|
||||
#/
|
||||
|
36
animscripts/custom.gsc
Normal file
36
animscripts/custom.gsc
Normal file
@ -0,0 +1,36 @@
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\Utility;
|
||||
#include common_scripts\Utility;
|
||||
|
||||
// Note that this script is called from the level script command animscripted, only for AI. If animscripted
|
||||
// is done on a script model, this script is not called - startscriptedanim is called directly.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
main()
|
||||
{
|
||||
//thread [[anim.println]]("Entering animscripts\\scripted. anim: ",self.codeScripted["anim"],", notify: ",self.codeScripted["notifyName"],", dialogue: ",self.scripted_dialogue,", facial: ",self.facial_animation, "root: ", self.codeScripted["root"]);#/
|
||||
self endon( "death" );
|
||||
|
||||
// wait (0);
|
||||
self notify( "killanimscript" );
|
||||
self notify( "clearSuppressionAttack" );
|
||||
self.a.suppressingEnemy = false;
|
||||
|
||||
|
||||
self.codeScripted[ "root" ] = %body; // TEMP!
|
||||
|
||||
self endon( "end_sequence" );
|
||||
// Causes potential variable overflow in Stalingrad
|
||||
// self thread DebugPrintEndSequence();
|
||||
|
||||
animation = %sprint_loop_distant; // Hardcoded default
|
||||
if ( isdefined( self.node.script_animation ) )
|
||||
{
|
||||
animation = self.node.script_animation;
|
||||
}
|
||||
|
||||
self setFlaggedAnimRestart( "custom", animation, 1, .1, 1.0 );
|
||||
|
||||
wait( 5.0 );
|
||||
self lookForBetterCover();
|
||||
}
|
1773
animscripts/death.gsc
Normal file
1773
animscripts/death.gsc
Normal file
File diff suppressed because it is too large
Load Diff
302
animscripts/door.gsc
Normal file
302
animscripts/door.gsc
Normal file
@ -0,0 +1,302 @@
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\utility;
|
||||
#include animscripts\shared;
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
doorGrenadeInterval = 5000;
|
||||
maxDistDoorToEnemySq = 600 * 600;
|
||||
|
||||
doorEnterExitCheck()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
if ( isdefined( self.disableDoorBehavior ) )
|
||||
return;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
doorNode = self getDoorPathNode();
|
||||
if ( isdefined( doorNode ) )
|
||||
break;
|
||||
|
||||
wait 0.2;
|
||||
}
|
||||
|
||||
goingInDoor = ( doorNode.type == "Door Interior" ) || self compareNodeDirToPathDir( doorNode );
|
||||
|
||||
if ( goingInDoor )
|
||||
self doorEnter( doorNode );
|
||||
else
|
||||
self doorExit( doorNode );
|
||||
|
||||
// waittill doorNode changes
|
||||
while ( 1 )
|
||||
{
|
||||
newDoorNode = self getDoorPathNode();
|
||||
if ( !isdefined( newDoorNode ) || newDoorNode != doorNode )
|
||||
break;
|
||||
|
||||
wait 0.2;
|
||||
}
|
||||
|
||||
self thread doorEnterExitCheck();
|
||||
}
|
||||
|
||||
teamFlashBangImmune()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self.teamFlashbangImmunity = true;
|
||||
wait 5;
|
||||
self.teamFlashbangImmunity = undefined;
|
||||
}
|
||||
|
||||
|
||||
doDoorGrenadeThrow( node )
|
||||
{
|
||||
self thread teamFlashBangImmune();
|
||||
|
||||
if ( self.grenadeWeapon == "flash_grenade" )
|
||||
self notify( "flashbang_thrown" );
|
||||
|
||||
self OrientMode( "face current" );
|
||||
node.nextDoorGrenadeTime = gettime() + doorGrenadeInterval;
|
||||
self.minInDoorTime = gettime() + 100000; // hack to not forget going indoor
|
||||
|
||||
self notify( "move_interrupt" );
|
||||
self.update_move_anim_type = undefined;
|
||||
|
||||
self clearanim( %combatrun, 0.2 );
|
||||
self.a.movement = "stop";
|
||||
self waittill( "done_grenade_throw" );
|
||||
self OrientMode( "face default" );
|
||||
|
||||
self.minInDoorTime = gettime() + 5000;
|
||||
|
||||
self.grenadeWeapon = self.oldGrenadeWeapon;
|
||||
self.oldGrenadeWeapon = undefined;
|
||||
|
||||
self animscripts\run::endFaceEnemyAimTracking();
|
||||
self thread animscripts\move::pathChangeCheck();
|
||||
self thread animscripts\move::restartMoveLoop( true );
|
||||
}
|
||||
|
||||
|
||||
// try throwing grenade before entering door
|
||||
doorEnter_TryGrenade( node, grenadeType, ricochet, minDistSq, checkInterval )
|
||||
{
|
||||
safeCheckDone = false;
|
||||
throwAttempts = 3;
|
||||
throwAnim = undefined;
|
||||
throwAnim = %CQB_stand_grenade_throw;
|
||||
|
||||
doorForward = anglesToForward( node.angles );
|
||||
if ( node.type == "Door Interior" && !( self compareNodeDirToPathDir( node ) ) )
|
||||
doorForward = -1 * doorForward;
|
||||
|
||||
doorPos = ( node.origin[ 0 ], node.origin[ 1 ], node.origin[ 2 ] + 64 );
|
||||
throwPos = doorPos;
|
||||
|
||||
if ( ricochet )
|
||||
{
|
||||
doorPlane = AnglesToRight( node.angles );
|
||||
dirToDoor = node.origin - self.origin;
|
||||
|
||||
// upto 20 units to left or right of door depending on direction to door to make it likely to bounce off door edge
|
||||
projLength = vectordot( doorPlane, dirToDoor );
|
||||
if ( projLength > 20 )
|
||||
projLength = 20;
|
||||
else if ( projLength < - 20 )
|
||||
projLength = -20;
|
||||
|
||||
throwPos = doorPos + projLength * doorPlane;
|
||||
}
|
||||
|
||||
while ( throwAttempts > 0 )
|
||||
{
|
||||
if ( isdefined( self.grenade ) || !isdefined( self.enemy ) )
|
||||
return;
|
||||
|
||||
if ( onSameSideOfDoor( node, doorForward ) )
|
||||
return;
|
||||
|
||||
if ( !self seeRecently( self.enemy, 0.2 ) && self.a.pose == "stand" && distance2DAndHeightCheck( self.enemy.origin - node.origin, maxDistDoorToEnemySq, 128 * 128 ) )
|
||||
{
|
||||
if ( isdefined( node.nextDoorGrenadeTime ) && node.nextDoorGrenadeTime > gettime() )
|
||||
return;
|
||||
|
||||
if ( self canShootEnemy() )
|
||||
return;
|
||||
|
||||
// too close to door
|
||||
dirToDoor = node.origin - self.origin;
|
||||
if ( lengthSquared( dirToDoor ) < minDistSq )
|
||||
return;
|
||||
|
||||
// don't throw backwards
|
||||
if ( vectordot( dirToDoor, doorForward ) < 0 )
|
||||
return;
|
||||
|
||||
self.oldGrenadeWeapon = self.grenadeWeapon;
|
||||
self.grenadeWeapon = grenadeType;
|
||||
|
||||
self setActiveGrenadeTimer( self.enemy );
|
||||
|
||||
if ( !safeCheckDone )
|
||||
{
|
||||
checkPos = doorPos + ( doorForward * 100 );
|
||||
if ( !( self isGrenadePosSafe( self.enemy, checkPos, 128 ) ) )
|
||||
return;
|
||||
}
|
||||
|
||||
safeCheckDone = true; // do this only once but do isGrenadePosSafe as late as possible
|
||||
|
||||
if ( TryGrenadeThrow( self.enemy, throwPos, throwAnim, getGrenadeThrowOffset( throwAnim ), true, false, true ) )
|
||||
{
|
||||
self doDoorGrenadeThrow( node );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throwAttempts -- ;
|
||||
wait checkInterval;
|
||||
|
||||
// check if door node has past
|
||||
newNode = self getDoorPathNode();
|
||||
if ( !isdefined( newNode ) || newNode != node )
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inDoorCqbToggleCheck()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
if ( isdefined( self.disableDoorBehavior ) )
|
||||
return;
|
||||
|
||||
self.isInDoor = false;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( self isInDoor() && !self.doingAmbush )
|
||||
{
|
||||
doorEnter_enable_cqbwalk();
|
||||
}
|
||||
else if ( !isdefined( self.minInDoorTime ) || self.minInDoorTime < gettime() )
|
||||
{
|
||||
self.minInDoorTime = undefined;
|
||||
doorExit_disable_cqbwalk();
|
||||
}
|
||||
|
||||
wait 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// substitute for enable_cqbwalk so LD can always disable cqb
|
||||
doorEnter_enable_cqbwalk()
|
||||
{
|
||||
if ( !isdefined( self.neverEnableCQB ) && !self.doingAmbush )
|
||||
{
|
||||
self.isInDoor = true;
|
||||
if ( !isdefined( self.cqbWalking ) || !self.cqbWalking )
|
||||
enable_cqbwalk( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// substitute for disable_cqbwalk so LD can force CQB even after exiting to outdoor
|
||||
doorExit_disable_cqbwalk()
|
||||
{
|
||||
if ( !isdefined( self.cqbEnabled ) )
|
||||
{
|
||||
self.isInDoor = false;
|
||||
if ( isdefined( self.cqbWalking ) && self.cqbWalking )
|
||||
disable_cqbwalk();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
maxFragDistSq = 750 * 750;
|
||||
minFragDistSq = 550 * 550;
|
||||
maxFlashDistSq = 192 * 192;
|
||||
minFlashDistSq = 64 * 64;
|
||||
maxFragHeightDiffSq = 160 * 160;
|
||||
maxFlashHeightDiffSq = 80 * 80;
|
||||
|
||||
distance2DAndHeightCheck( vec, dist2DSq, heightSq )
|
||||
{
|
||||
return( ( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] ) < dist2DSq ) && ( ( vec[ 2 ] * vec[ 2 ] ) < heightSq );
|
||||
}
|
||||
|
||||
|
||||
onSameSideOfDoor( node, doorForward )
|
||||
{
|
||||
assert( isdefined( self.enemy ) );
|
||||
|
||||
selfToDoor = node.origin - self.origin;
|
||||
enemyToDoor = node.origin - self.enemy.origin;
|
||||
|
||||
return( vectordot( selfToDoor, doorForward ) * vectordot( enemyToDoor, doorForward ) > 0 );
|
||||
}
|
||||
|
||||
|
||||
doorEnter( node )
|
||||
{
|
||||
// try frag
|
||||
while ( 1 )
|
||||
{
|
||||
if ( isdefined( self.doorFragChance ) && ( self.doorFragChance == 0 || self.doorFragChance < randomfloat( 1 ) ) )
|
||||
break;
|
||||
|
||||
if ( distance2DAndHeightCheck( self.origin - node.origin, maxFragDistSq, maxFragHeightDiffSq ) )
|
||||
{
|
||||
self doorEnter_TryGrenade( node, "fraggrenade", false, minFragDistSq, 0.3 );
|
||||
|
||||
node = self getDoorPathNode();
|
||||
if ( !isdefined( node ) )
|
||||
return;
|
||||
|
||||
break;
|
||||
}
|
||||
wait 0.1;
|
||||
}
|
||||
|
||||
// try flashbang
|
||||
while ( 1 )
|
||||
{
|
||||
if ( distance2DAndHeightCheck( self.origin - node.origin, maxFlashDistSq, maxFlashHeightDiffSq ) )
|
||||
{
|
||||
self doorEnter_enable_cqbwalk();
|
||||
self.minInDoorTime = gettime() + 6000;
|
||||
|
||||
if ( isdefined( self.doorFlashChance ) && ( self.doorFlashChance == 0 || self.doorFlashChance < randomfloat( 1 ) ) )
|
||||
return;
|
||||
|
||||
self doorEnter_TryGrenade( node, "flash_grenade", true, minFlashDistSq, 0.2 );
|
||||
return;
|
||||
}
|
||||
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
doorExit( node )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
if ( !self.isInDoor || distanceSquared( self.origin, node.origin ) < 32 * 32 )
|
||||
{
|
||||
//self doorExit_disable_cqbwalk();
|
||||
return;
|
||||
}
|
||||
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
75
animscripts/ec_lgv/stand.gsc
Normal file
75
animscripts/ec_lgv/stand.gsc
Normal file
@ -0,0 +1,75 @@
|
||||
#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 = %LGVGunner_aim;
|
||||
|
||||
self.additiveTurretRotateLeft = %nx_tp_chinese_lgv_gunner_aim_2_add;
|
||||
self.additiveTurretRotateRight = %nx_tp_chinese_lgv_gunner_aim_4_add;
|
||||
self.additiveRotateRoot = %additive_LGVGunner_aim_leftright;
|
||||
|
||||
self.additiveTurretIdle = %nx_tp_chinese_lgv_gunner_idle;
|
||||
self.additiveTurretDriveIdle = %nx_tp_chinese_lgv_gunner_driveidle;
|
||||
self.additiveTurretFire = %nx_tp_chinese_lgv_gunner_fire;
|
||||
self.additiveUsegunRoot = %additive_LGVGunner_usegun;
|
||||
|
||||
self.turretDeathAnimRoot = %LGVGunner_death;
|
||||
self.turretDeathAnim = %nx_tp_chinese_lgv_gunner_death;
|
||||
self.turretPainAnims[ 0 ] = %nx_tp_chinese_lgv_gunner_pain;
|
||||
|
||||
self.turretReloadAnim = %nx_tp_chinese_lgv_gunner_rechamber;
|
||||
|
||||
self.turretSpecialAnimsRoot = %LGVGunner;
|
||||
arr = [];
|
||||
arr[ "nx_tp_chinese_lgv_gunner_rechamber" ] = %nx_tp_chinese_lgv_gunner_rechamber;
|
||||
self.turretSpecialAnims = arr;
|
||||
|
||||
turret setup_turret_anims();
|
||||
|
||||
self thread animscripts\hummer_turret\minigun_code::main( turret );
|
||||
|
||||
// Setting verious parameters for LGV turret after minigun_code::main, which sets it to hummer values.
|
||||
|
||||
shots_per_second = turret GetTurretShotsPerSecondAI();
|
||||
if ( shots_per_second > 0.0 )
|
||||
{
|
||||
turret.fireInterval = 1.0 / shots_per_second;
|
||||
}
|
||||
turret.secsOfFiringBeforeReload = 15.0;
|
||||
turret.reloadDuration = 2.17;
|
||||
turret.centerTurretForReload = true;
|
||||
turret.extraFireTime_min = 0;
|
||||
turret.extraFireTime_max = 1;
|
||||
turret.wait_duration_after_aiming_before_firing = 0.2;
|
||||
|
||||
turret thread reload_fx();
|
||||
}
|
||||
|
||||
#using_animtree( "vehicles" );
|
||||
setup_turret_anims()
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
self.passenger2turret_anime = %nx_vh_chinese_lgv_gunner_mount_turret;
|
||||
self.turret2passenger_anime = %nx_vh_chinese_lgv_gunner_getout_turret;
|
||||
}
|
||||
|
||||
reload_fx()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
self waittill( "starting_reload" );
|
||||
|
||||
playFXOnTag( level._effect[ "nx_chinese_lgv_turret_steam" ], self, "tag_origin" );
|
||||
playFXOnTag( level._effect[ "nx_chinese_lgv_turret_steam_muzzle" ], self, "tag_flash" );
|
||||
}
|
||||
}
|
522
animscripts/face.gsc
Normal file
522
animscripts/face.gsc
Normal file
@ -0,0 +1,522 @@
|
||||
// face.gsc
|
||||
// Supposed to handle all facial and dialogue animations from regular scripts.
|
||||
//#using_animtree ("generic_human"); - This file doesn't call animations directly.
|
||||
|
||||
|
||||
|
||||
InitCharacterFace()
|
||||
{
|
||||
if ( !anim.useFacialAnims )
|
||||
return;
|
||||
|
||||
// Does any per-character initialization which is required by this facial animation script.
|
||||
// InitLevelFace must be called before this function.
|
||||
if ( !isDefined( self.a.currentDialogImportance ) )
|
||||
{
|
||||
self.a.currentDialogImportance = 0; // Indicates that we are not currently saying anything.
|
||||
self.a.idleFace = anim.alertface;
|
||||
self.faceWaiting = [];
|
||||
self.faceLastNotifyNum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Makes a character say the specified line in his voice, if he's not already saying something more
|
||||
// important.
|
||||
SayGenericDialogue( typeString )
|
||||
{
|
||||
// First pick a random voice number for our character. We have to do this every time because it's
|
||||
// possible for the character to be changed after the level loads (generally right before it starts).
|
||||
// Use (entity number) modulus (number of voices) to get a consistent result.
|
||||
|
||||
if ( ( self.voice == "multilingual" ) || ( self.voice == "italian" ) || ( self.voice == "german" ) || ( self.voice == "spanish" ) )
|
||||
voiceString = "russian";
|
||||
else
|
||||
voiceString = self.voice;
|
||||
|
||||
ASSERT( isDefined( voiceString ) );
|
||||
|
||||
voicenum = undefined;
|
||||
numVoices = undefined;
|
||||
|
||||
switch( voiceString )
|
||||
{
|
||||
case "american":
|
||||
numVoices = anim.numAmericanVoices;
|
||||
break;
|
||||
|
||||
case "seal":
|
||||
voiceString = "navyseal"; // soundaliases use the string "navyseal" (not "seal")
|
||||
numVoices = anim.numNavySealVoices;
|
||||
break;
|
||||
|
||||
case "taskforce":
|
||||
numVoices = anim.numTaskForceVoices;
|
||||
break;
|
||||
|
||||
case "secretservice":
|
||||
numVoices = anim.numSecretServiceVoices;
|
||||
break;
|
||||
|
||||
case "british":
|
||||
numVoices = anim.numBritishVoices;
|
||||
break;
|
||||
|
||||
case "russian":
|
||||
numVoices = anim.numRussianVoices;
|
||||
break;
|
||||
|
||||
case "arab":
|
||||
numVoices = anim.numArabVoices;
|
||||
break;
|
||||
|
||||
case "portuguese":
|
||||
numVoices = anim.numPortugueseVoices;
|
||||
break;
|
||||
|
||||
case "shadowcompany":
|
||||
numVoices = anim.numShadowCompanyVoices;
|
||||
break;
|
||||
|
||||
case "jswc":
|
||||
numVoices = anim.numJSWCVoices;
|
||||
break;
|
||||
|
||||
case "usop":
|
||||
numVoices = anim.numUSOPVoices;
|
||||
break;
|
||||
|
||||
case "indonesian":
|
||||
voiceString = "indonesian";
|
||||
numVoices = anim.numIndonesianVoices;
|
||||
|
||||
case "mexican":
|
||||
//voiceString = "mexican"; //temporarily using arab vo in sound_generic.csv
|
||||
numVoices = anim.numIndonesianVoices;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT( IsDefined( numVoices ) );
|
||||
|
||||
voicenum = 1 + ( self GetEntityNumber() % numVoices );
|
||||
|
||||
ASSERT( IsDefined( voicenum ) );
|
||||
|
||||
voiceString = voiceString + "_" + voicenum;
|
||||
|
||||
faceAnim = undefined;
|
||||
|
||||
switch( typeString )
|
||||
{
|
||||
|
||||
case "meleecharge":
|
||||
case "meleeattack":
|
||||
// faceAnim = animscripts\face::ChooseAnimFromSet(anim.meleeFace);
|
||||
importance = 0.5;
|
||||
break;
|
||||
case "flashbang":
|
||||
// faceAnim = animscripts\face::ChooseAnimFromSet(anim.painFace);
|
||||
importance = 0.7;
|
||||
break;
|
||||
case "pain":
|
||||
// faceAnim = animscripts\face::ChooseAnimFromSet(anim.painFace);
|
||||
importance = 0.9;
|
||||
break;
|
||||
case "death":
|
||||
// faceAnim = animscripts\face::ChooseAnimFromSet(anim.deathFace);
|
||||
importance = 1.0;
|
||||
break;
|
||||
default:
|
||||
println( "Unexpected generic dialog string: " + typeString );
|
||||
importance = 0.3;
|
||||
break;
|
||||
}
|
||||
// Now assemble the sound alias and try to play it.
|
||||
soundAlias = "generic_" + typeString + "_" + voiceString;
|
||||
// Note that faceAnim is allowed to be undefined.
|
||||
self thread PlayFaceThread( faceAnim, soundAlias, importance );
|
||||
}
|
||||
|
||||
SetIdleFaceDelayed( facialAnimationArray )
|
||||
{
|
||||
self animscripts\battleChatter::playBattleChatter();
|
||||
|
||||
self.a.idleFace = facialAnimationArray;
|
||||
}
|
||||
|
||||
// Sets the facial expression to return to when not saying dialogue.
|
||||
// The array is animation1, weight1, animation2, weight2, etc. The animations will play in turn - each time
|
||||
// one finishes a new one will be chosen randomly based on weight.
|
||||
SetIdleFace( facialAnimationArray )
|
||||
{
|
||||
if ( !anim.useFacialAnims )
|
||||
return;
|
||||
|
||||
self animscripts\battleChatter::playBattleChatter();
|
||||
|
||||
self.a.idleFace = facialAnimationArray;
|
||||
self PlayIdleFace();
|
||||
}
|
||||
|
||||
// Makes the character play the specified sound and animation. The anim and the sound are optional - you
|
||||
// can just defined one if you don't have both.
|
||||
// Generally, importance should be in the range of 0.6-0.8 for scripted dialogue.
|
||||
// Importance is a float, from 0 to 1.
|
||||
// 0.0 - Idle expressions
|
||||
// 0.1-0.5 - most generic dialogue
|
||||
// 0.6-0.8 - most scripted dialogue
|
||||
// 0.9 - pain
|
||||
// 1.0 - death
|
||||
// Importance can also be one of these strings: "any", "pain" or "death", which specfies what sounds can
|
||||
// interrupt this one.
|
||||
SaySpecificDialogue( facialanim, soundAlias, importance, notifyString, waitOrNot, timeToWait )
|
||||
{
|
||||
///("SaySpecificDialog, facial: ",facialanim,", sound: ",soundAlias,", importance: "+importance+", notify: ",notifyString, ", WaitOrNot: ", waitOrNot, ", timeToWait: ", timeToWait);#/
|
||||
self thread PlayFaceThread( facialanim, soundAlias, importance, notifyString, waitOrNot, timeToWait );
|
||||
}
|
||||
|
||||
// Takes an array with a set of "anim" entries and a corresponding set of "weight" entries.
|
||||
ChooseAnimFromSet( animSet )
|
||||
{
|
||||
return; // Facial animations are now part of full body aniamtions
|
||||
/*
|
||||
if (!anim.useFacialAnims)
|
||||
return;
|
||||
// First, normalize the weights.
|
||||
totalWeight = 0;
|
||||
numAnims = animSet["anim"].size;
|
||||
for ( i=0 ; i<numAnims ; i++ )
|
||||
{
|
||||
totalWeight += animSet["weight"][i];
|
||||
}
|
||||
for ( i=0 ; i<numAnims ; i++ )
|
||||
{
|
||||
animSet["weight"][i] = animSet["weight"][i] / totalWeight;
|
||||
}
|
||||
|
||||
// Now choose an animation.
|
||||
rand = randomfloat(1);
|
||||
runningTotal = 0;
|
||||
chosenAnim = undefined;
|
||||
for ( i=0 ; i<numAnims ; i++ )
|
||||
{
|
||||
runningTotal += animSet["weight"][i];
|
||||
if (runningTotal >= rand)
|
||||
{
|
||||
chosenAnim = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEX(isDefined(chosenAnim), "Logic error in ChooseAnimFromSet. Rand is " + rand + ".");
|
||||
return animSet["anim"][chosenAnim];
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-----------------------------------------------------
|
||||
// Housekeeping functions - these are for internal use
|
||||
//-----------------------------------------------------
|
||||
|
||||
// PlayIdleFace doesn't force an idle animation to play - it will interrupt a current idle animation, but it
|
||||
// won't play over a more important animation, like dialogue.
|
||||
PlayIdleFace()
|
||||
{
|
||||
return; // Idle facial animations are now in the full - body animations.
|
||||
}
|
||||
|
||||
// PlayFaceThread is the workhorse of the system - it checks the importance, and if it's high enough, it
|
||||
// plays the animation and/or sound specified.
|
||||
// The waitOrNot parameter specifies what to do if another animation/sound is already playing.
|
||||
// Options: "wait" or undefined. TimeToWait is an optional timeout time for waiting.
|
||||
// Waiting faces are queued.
|
||||
PlayFaceThread( facialanim, soundAlias, importance, notifyString, waitOrNot, timeToWait )
|
||||
{
|
||||
self.a.facialAnimDone = true;
|
||||
self.a.facialSoundDone = true;
|
||||
|
||||
if ( isdefined( notifyString ) )
|
||||
{
|
||||
if ( isDefined( soundAlias ) )
|
||||
{
|
||||
self playsound( soundAlias, "animscript facesound" + notifyString, true );
|
||||
// so placefacethread doesnt block
|
||||
self thread WaitForFaceSound( notifyString );
|
||||
}
|
||||
}
|
||||
else
|
||||
self playsound( soundAlias );
|
||||
|
||||
if ( !anim.useFacialAnims )
|
||||
return;
|
||||
|
||||
InitCharacterFace();
|
||||
|
||||
if ( !isDefined( facialanim ) && !isDefined( soundAlias ) )
|
||||
{
|
||||
// This is not actually an error condition but it might mess up the calling script, so better to catch it now.
|
||||
assertEX( 0, "Either facialanim or soundAlias should be defined when calling PlayFaceThread or SaySpecificDialogue" );
|
||||
if ( isDefined( notifyString ) )
|
||||
{
|
||||
wait( 0 ); // This allows the calling script to get to a point where it's waiting for the notify
|
||||
self.faceResult = "failed";
|
||||
self notify( notifyString );
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
self endon( "death" );
|
||||
|
||||
if ( isString( importance ) )
|
||||
{
|
||||
switch( importance )
|
||||
{
|
||||
case "any":
|
||||
importance = 0.1;
|
||||
break;
|
||||
|
||||
case "pain":
|
||||
importance = 0.9;
|
||||
break;
|
||||
|
||||
case "death":
|
||||
importance = 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ( importance <= self.a.currentDialogImportance ) && ( isDefined( waitOrNot ) && ( waitOrNot == "wait" ) ) )
|
||||
{
|
||||
//("Face: Waiting to play sound: ",soundAlias,", anim: ",facialanim,", ", notifyString,(", importance "+importance+", old one "+self.a.currentDialogImportance));#/
|
||||
// Put this face at the end of the queue
|
||||
thisEntryNum = self.faceWaiting.size;
|
||||
thisNotifyNum = self.faceLastNotifyNum + 1;
|
||||
self.faceWaiting[ thisEntryNum ][ "facialanim" ] = facialanim;
|
||||
self.faceWaiting[ thisEntryNum ][ "soundAlias" ] = soundAlias;
|
||||
self.faceWaiting[ thisEntryNum ][ "importance" ] = importance;
|
||||
self.faceWaiting[ thisEntryNum ][ "notifyString" ] = notifyString;
|
||||
self.faceWaiting[ thisEntryNum ][ "waitOrNot" ] = waitOrNot;
|
||||
self.faceWaiting[ thisEntryNum ][ "timeToWait" ] = timeToWait;
|
||||
self.faceWaiting[ thisEntryNum ][ "notifyNum" ] = thisNotifyNum; // Unique identifier.
|
||||
|
||||
// What we do now is, wait for both the notify and the time. If the time expires first, we give
|
||||
// up and remove this entry from the queue. If the notify happens first, we stop waiting for the
|
||||
// time and we play the face.
|
||||
self thread PlayFace_WaitForNotify( ( "animscript face stop waiting " + self.faceWaiting[ thisEntryNum ][ "notifyNum" ] ), "Face done waiting", "Face done waiting" );
|
||||
if ( isDefined( timeToWait ) )
|
||||
self thread PlayFace_WaitForTime( timeToWait, "Face done waiting", "Face done waiting" );
|
||||
self waittill( "Face done waiting" );
|
||||
|
||||
// First, find the entry, since it may have been moved.
|
||||
thisEntryNum = undefined;
|
||||
for ( i = 0 ; i < self.faceWaiting.size ; i++ )
|
||||
{
|
||||
if ( self.faceWaiting[ i ][ "notifyNum" ] == thisNotifyNum )
|
||||
{
|
||||
thisEntryNum = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEX( isDefined( thisEntryNum ) );
|
||||
|
||||
if ( self.a.faceWaitForResult == "notify" )
|
||||
{
|
||||
// Play the face.
|
||||
PlayFaceThread( self.faceWaiting[ thisEntryNum ][ "facialanim" ],
|
||||
self.faceWaiting[ thisEntryNum ][ "soundAlias" ],
|
||||
self.faceWaiting[ thisEntryNum ][ "importance" ],
|
||||
self.faceWaiting[ thisEntryNum ][ "notifyString" ]
|
||||
);
|
||||
}
|
||||
else // ie We timed out.
|
||||
{
|
||||
if ( isDefined( notifyString ) )
|
||||
{
|
||||
self.faceResult = "failed";
|
||||
self notify( notifyString );
|
||||
}
|
||||
}
|
||||
|
||||
// Remove this entry from the queue. If any entries have been added after this one, move them
|
||||
// forward.
|
||||
for ( i = thisEntryNum + 1 ; i < self.faceWaiting.size ; i++ )
|
||||
{
|
||||
self.faceWaiting[ i - 1 ][ "facialanim" ] = self.faceWaiting[ i ][ "facialanim" ];
|
||||
self.faceWaiting[ i - 1 ][ "soundAlias" ] = self.faceWaiting[ i ][ "soundAlias" ];
|
||||
self.faceWaiting[ i - 1 ][ "importance" ] = self.faceWaiting[ i ][ "importance" ];
|
||||
self.faceWaiting[ i - 1 ][ "notifyString" ] = self.faceWaiting[ i ][ "notifyString" ];
|
||||
self.faceWaiting[ i - 1 ][ "waitOrNot" ] = self.faceWaiting[ i ][ "waitOrNot" ];
|
||||
self.faceWaiting[ i - 1 ][ "timeToWait" ] = self.faceWaiting[ i ][ "timeToWait" ];
|
||||
self.faceWaiting[ i - 1 ][ "notifyNum" ] = self.faceWaiting[ i ][ "notifyNum" ];
|
||||
}
|
||||
self.faceWaiting[ self.faceWaiting.size - 1 ] = undefined;
|
||||
|
||||
}
|
||||
else if ( importance >= self.a.currentDialogImportance )
|
||||
{
|
||||
// End any threads that are waiting on current facial animations or sounds.
|
||||
self notify( "end current face" );
|
||||
self endon( "end current face" );
|
||||
//("Face: Playing facial sound/animation: ", facialanim, ", ",soundAlias,", ",notifyString, ", ",importance);#/
|
||||
//if (self.a.currentDialogImportance > 0)
|
||||
//{
|
||||
//("Face: Interrupted facial sound/animation: ",self.a.currentDialogSound,", ",self.a.currentDialogNotifyString, ", ",self.a.currentDialogImportance);#/
|
||||
//}
|
||||
if ( isDefined( notifyString ) )
|
||||
{
|
||||
if ( isDefined( self.a.currentDialogNotifyString ) )
|
||||
{
|
||||
self.faceResult = "interrupted";
|
||||
self notify( self.a.currentDialogNotifyString );
|
||||
}
|
||||
}
|
||||
// Remember what we're doing, so we can decide what to do if another face tries to interrupt this one.
|
||||
self.a.currentDialogImportance = importance;
|
||||
self.a.currentDialogSound = soundAlias; // ( This one is only used for debugging. )
|
||||
self.a.currentDialogNotifyString = notifyString;
|
||||
|
||||
// Set finished to true so that if we don't play one of these, we don't have to wait for it to finish.
|
||||
self.a.facialAnimDone = true;
|
||||
self.a.facialSoundDone = true;
|
||||
// Play the anim and sound, if they are defined.
|
||||
if ( isDefined( facialanim ) )
|
||||
{
|
||||
// self setanim(%facial, 0.01, .1, 1); // This doesn't work for non-AI
|
||||
self setflaggedanimknobrestart( "animscript faceanim", facialanim, 1, .1, 1 );
|
||||
self.a.facialAnimDone = false;
|
||||
self thread WaitForFacialAnim();
|
||||
//("Face: Waiting for facial animation ", facialanim);#/
|
||||
}
|
||||
//else TODO play a generic, looping facial animation.
|
||||
if ( isDefined( soundAlias ) )
|
||||
{
|
||||
// TEMP These lines break sound for most lines because of a bug in facial animation (code bug?). When that
|
||||
// bug is fixed, put these lines back in.
|
||||
// if ( isDefined(facialanim) && animhasnotetrack(facialanim, "dialogue"))
|
||||
// {
|
||||
// self waittillmatch ("animscript faceanim", "dialogue");
|
||||
// }
|
||||
self playsound( soundAlias, "animscript facesound", true );
|
||||
self.a.facialSoundDone = false;
|
||||
self thread WaitForFaceSound();
|
||||
//("Face: Waiting for sound ",soundAlias);#/
|
||||
}
|
||||
// Now wait until both animation and sound are finished
|
||||
while ( ( !self.a.facialAnimDone ) || ( !self.a.facialSoundDone ) )
|
||||
{
|
||||
self waittill( "animscript facedone" );
|
||||
}
|
||||
// Set importance to 0 so that other facial anims (like the idle) can play.
|
||||
//("Face: Finished facial sound: ",soundAlias,", animation: ",facialanim," notify: ",notifyString,", importance ",importance);#/
|
||||
self.a.currentDialogImportance = 0;
|
||||
self.a.currentDialogSound = undefined;
|
||||
self.a.currentDialogNotifyString = undefined;
|
||||
if ( isDefined( notifyString ) )
|
||||
{
|
||||
self.faceResult = "finished";
|
||||
self notify( notifyString );
|
||||
}
|
||||
if ( isDefined( self.faceWaiting ) && ( self.faceWaiting.size > 0 ) )
|
||||
{
|
||||
// Find out which face we want to play next. Look through the queue for the highest priority
|
||||
// face. If we find more than one with the same importance, choose the one that was added first.
|
||||
maxImportance = 0;
|
||||
nextFaceNum = 1;
|
||||
//("Choosing next face. List is:");#/
|
||||
for ( i = 0 ; i < self.faceWaiting.size ; i++ )
|
||||
{
|
||||
/*
|
||||
println]](" ",i," ", (self.faceWaiting[i]["facialanim"]),", ",
|
||||
(self.faceWaiting[i]["soundAlias"]),", ",
|
||||
(self.faceWaiting[i]["importance"]),", ",
|
||||
(self.faceWaiting[i]["notifyString"])
|
||||
);#/
|
||||
*/
|
||||
if ( self.faceWaiting[ i ][ "importance" ] > maxImportance )
|
||||
{
|
||||
maxImportance = self.faceWaiting[ i ][ "importance" ];
|
||||
nextFaceNum = i;
|
||||
}
|
||||
}
|
||||
//("Chose ", nextFaceNum);#/
|
||||
// Notify the entry in the queue, to play.
|
||||
self notify( "animscript face stop waiting " + self.faceWaiting[ nextFaceNum ][ "notifyNum" ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
// We're done. Set an idle face going before we exit.
|
||||
// TODO Make the idle face play whenever the animation finishes, for cases when it finishes before the sound.
|
||||
if ( IsAI( self ) )
|
||||
{
|
||||
self PlayIdleFace();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isDefined( notifyString ) )
|
||||
{
|
||||
self.faceResult = "failed";
|
||||
self notify( notifyString );
|
||||
}
|
||||
//("Face: Didn't play facial sound: ",soundAlias,", animation: ",facialanim," notify: ",notifyString,", importance ",importance,", old one ",self.a.currentDialogImportance);#/
|
||||
}
|
||||
}
|
||||
|
||||
WaitForFacialAnim() // Used solely by PlayFaceThread
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "end current face" );
|
||||
self animscripts\shared::DoNoteTracks( "animscript faceanim" );
|
||||
self.a.facialAnimDone = true;
|
||||
self notify( "animscript facedone" );
|
||||
}
|
||||
|
||||
WaitForFaceSound( msg ) // Used solely by PlayFaceThread
|
||||
{
|
||||
self endon( "death" );
|
||||
self waittill( "animscript facesound" + msg );
|
||||
self notify( msg );
|
||||
}
|
||||
|
||||
PlayFace_WaitForNotify( waitForString, notifyString, killmeString )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( killmeString );
|
||||
self waittill( waitForString );
|
||||
self.a.faceWaitForResult = "notify";
|
||||
self notify( notifyString );
|
||||
}
|
||||
|
||||
PlayFace_WaitForTime( time, notifyString, killmeString )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( killmeString );
|
||||
wait( time );
|
||||
self.a.faceWaitForResult = "time";
|
||||
self notify( notifyString );
|
||||
}
|
||||
|
||||
|
||||
#using_animtree( "generic_human" );// This section of the file calls animations directly since it's only used on AI.
|
||||
InitLevelFace()
|
||||
{
|
||||
// Does per-level initialization of facial stuff.
|
||||
|
||||
// These numbers indicate how many different sound aliases there are in dialog_generic.csv for each
|
||||
// nationality. This script will assign each guy a random voice number from 1 to the number indicated
|
||||
// for his voice nationality below. If we add a new voice type to sound_generic.csv, we need to update
|
||||
// these numbers accordingly.
|
||||
anim.numAmericanVoices = 8;
|
||||
anim.numNavySealVoices = 8;
|
||||
anim.numTaskForceVoices = 8;
|
||||
anim.numSecretServiceVoices = 8;
|
||||
anim.numBritishVoices = 8;
|
||||
anim.numRussianVoices = 8;
|
||||
anim.numArabVoices = 8;
|
||||
anim.numPortugueseVoices = 8;
|
||||
anim.numShadowCompanyVoices = 8;
|
||||
anim.numJSWCVoices = 4;
|
||||
anim.numUSOPVoices = 4;
|
||||
anim.numIndonesianVoices = 8;
|
||||
}
|
17
animscripts/first_frame.gsc
Normal file
17
animscripts/first_frame.gsc
Normal file
@ -0,0 +1,17 @@
|
||||
main()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "stop_first_frame" );
|
||||
self notify( "killanimscript" );
|
||||
self.pushable = 0;
|
||||
|
||||
self clearAnim( self.root_anim, 0.3 );
|
||||
// self setAnim( %body, 1, 0 ); // The %body node should always have weight 1.
|
||||
|
||||
self OrientMode( "face angle", self.angles[ 1 ] );
|
||||
|
||||
self setanim( level._scr_anim[ self._animname ][ self._first_frame_anim ], 1, 0, 0 );
|
||||
self._first_frame_anim = undefined;
|
||||
|
||||
self waittill( "killanimscript" );
|
||||
}
|
94
animscripts/flashed.gsc
Normal file
94
animscripts/flashed.gsc
Normal file
@ -0,0 +1,94 @@
|
||||
#include animscripts\Utility;
|
||||
#include animscripts\SetPoseMovement;
|
||||
#include animscripts\Combat_utility;
|
||||
#include maps\_anim;
|
||||
#include maps\_utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
initFlashed()
|
||||
{
|
||||
anim.flashAnimArray[ 0 ] = %exposed_flashbang_v1;
|
||||
anim.flashAnimArray[ 1 ] = %exposed_flashbang_v2;
|
||||
anim.flashAnimArray[ 2 ] = %exposed_flashbang_v3;
|
||||
anim.flashAnimArray[ 3 ] = %exposed_flashbang_v4;
|
||||
anim.flashAnimArray[ 4 ] = %exposed_flashbang_v5;
|
||||
|
||||
randomizeFlashAnimArray();
|
||||
|
||||
anim.flashAnimIndex = 0;
|
||||
}
|
||||
|
||||
randomizeFlashAnimArray()
|
||||
{
|
||||
for ( i = 0; i < anim.flashAnimArray.size; i++ )
|
||||
{
|
||||
switchwith = randomint( anim.flashAnimArray.size );
|
||||
temp = anim.flashAnimArray[ i ];
|
||||
anim.flashAnimArray[ i ] = anim.flashAnimArray[ switchwith ];
|
||||
anim.flashAnimArray[ switchwith ] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
getNextFlashAnim()
|
||||
{
|
||||
anim.flashAnimIndex++;
|
||||
if ( anim.flashAnimIndex >= anim.flashAnimArray.size )
|
||||
{
|
||||
anim.flashAnimIndex = 0;
|
||||
randomizeFlashAnimArray();
|
||||
}
|
||||
return anim.flashAnimArray[ anim.flashAnimIndex ];
|
||||
}
|
||||
|
||||
flashBangAnim( animation )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self setflaggedanimknoball( "flashed_anim", animation, %body, 0.2, randomFloatRange( 0.9, 1.1 ) );
|
||||
self animscripts\shared::DoNoteTracks( "flashed_anim" );
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
animscripts\utility::initialize( "flashed" );
|
||||
|
||||
flashDuration = self flashBangGetTimeLeftSec();
|
||||
if ( flashDuration <= 0 )
|
||||
return;
|
||||
|
||||
self animscripts\face::SayGenericDialogue( "flashbang" );
|
||||
|
||||
if ( isdefined( self.specialFlashedFunc ) )
|
||||
{
|
||||
self [[ self.specialFlashedFunc ]]();
|
||||
return;
|
||||
}
|
||||
|
||||
animation = getNextFlashAnim();
|
||||
flashBangedLoop( animation, flashDuration );
|
||||
}
|
||||
|
||||
flashBangedLoop( animation, duration )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
assert( isDefined( animation ) );
|
||||
assert( isDefined( duration ) );
|
||||
assert( duration > 0 );
|
||||
|
||||
if ( self.a.pose == "prone" )
|
||||
self ExitProneWrapper( 1 );
|
||||
|
||||
self.a.pose = "stand";
|
||||
self.allowdeath = true;
|
||||
|
||||
self thread flashBangAnim( animation );
|
||||
wait ( duration );
|
||||
|
||||
self notify( "stop_flashbang_effect" );
|
||||
self.flashed = false;
|
||||
}
|
91
animscripts/grenade_cower.gsc
Normal file
91
animscripts/grenade_cower.gsc
Normal file
@ -0,0 +1,91 @@
|
||||
#include animscripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
animscripts\utility::initialize( "grenadecower" );
|
||||
|
||||
if ( isdefined( self.grenadeCowerFunction ) )
|
||||
{
|
||||
self [[ self.grenadeCowerFunction ]]();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self.a.pose == "prone" )
|
||||
{
|
||||
// TODO: use an i-just-dived loop?
|
||||
|
||||
animscripts\stop::main();
|
||||
return; // Should never get to here
|
||||
}
|
||||
|
||||
self AnimMode( "zonly_physics" );
|
||||
self OrientMode( "face angle", self.angles[ 1 ] );
|
||||
|
||||
grenadeAngle = 0;
|
||||
|
||||
if ( isdefined( self.grenade ) )// failsafe
|
||||
grenadeAngle = AngleClamp180( vectorToAngles( self.grenade.origin - self.origin )[ 1 ] - self.angles[ 1 ] );
|
||||
else
|
||||
grenadeAngle = self.angles[ 1 ];
|
||||
|
||||
if ( self.a.pose == "stand" )
|
||||
{
|
||||
if ( isdefined( self.grenade ) && TryDive( grenadeAngle ) )
|
||||
return;
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "cowerstart", %exposed_squat_down_grenade_F, %body, 1, 0.2 );
|
||||
self animscripts\shared::DoNoteTracks( "cowerstart" );
|
||||
}
|
||||
self.a.pose = "crouch";
|
||||
self.a.movement = "stop";
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "cower", %exposed_squat_idle_grenade_F, %body, 1, 0.2 );
|
||||
self animscripts\shared::DoNoteTracks( "cower" );
|
||||
|
||||
self waittill( "never" );
|
||||
}
|
||||
|
||||
end_script()
|
||||
{
|
||||
self.safeToChangeScript = true;
|
||||
}
|
||||
|
||||
TryDive( grenadeAngle )
|
||||
{
|
||||
if ( randomint( 2 ) == 0 )
|
||||
return false;
|
||||
|
||||
if ( self.stairsState != "none" )
|
||||
return false;
|
||||
|
||||
diveAnim = undefined;
|
||||
if ( abs( grenadeAngle ) > 90 )
|
||||
{
|
||||
// grenade behind us
|
||||
diveAnim = %exposed_dive_grenade_B;
|
||||
}
|
||||
else
|
||||
{
|
||||
// grenade in front of us
|
||||
diveAnim = %exposed_dive_grenade_F;
|
||||
}
|
||||
|
||||
// when the dives are split into a dive, idle, and get up,
|
||||
// maybe we can get a better point to do the moveto check with
|
||||
moveBy = getMoveDelta( diveAnim, 0, 0.5 );
|
||||
diveToPos = self localToWorldCoords( moveBy );
|
||||
|
||||
if ( !self MayMoveToPoint( diveToPos ) )
|
||||
return false;
|
||||
|
||||
self.safeToChangeScript = false;
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "cowerstart", diveAnim, %body, 1, 0.2 );
|
||||
self animscripts\shared::DoNoteTracks( "cowerstart" );
|
||||
|
||||
self.safeToChangeScript = true;
|
||||
|
||||
return true;
|
||||
}
|
148
animscripts/grenade_return_throw.gsc
Normal file
148
animscripts/grenade_return_throw.gsc
Normal file
@ -0,0 +1,148 @@
|
||||
#include animscripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
// Grenade_return_throw
|
||||
// Picks up a grenade from 32 units in front of the character, and throws it.
|
||||
|
||||
main()
|
||||
{
|
||||
/#
|
||||
if ( getdvar( "scr_forcegrenadecower" ) == "on" && isdefined( self.grenade ) )
|
||||
{
|
||||
self OrientMode( "face angle", randomfloat( 360 ) );
|
||||
self animmode( "gravity" );
|
||||
wait .2;
|
||||
animscripts\grenade_cower::main();
|
||||
return;
|
||||
}
|
||||
#/
|
||||
|
||||
self orientMode( "face default" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
animscripts\utility::initialize( "grenade_return_throw" );
|
||||
|
||||
self animMode( "zonly_physics" );// Unlatch the feet
|
||||
|
||||
throwAnim = undefined;
|
||||
|
||||
throwDist = 1000;
|
||||
if ( isdefined( self.enemy ) )
|
||||
throwDist = distance( self.origin, self.enemy.origin );
|
||||
|
||||
// unused: grenade_return_running_kick_forward_1; kicks don't read well to player
|
||||
// unused: grenade_return_running_kick_forward_2
|
||||
// unused: %grenade_return_standing_throw_forward_2; similar to other ones
|
||||
|
||||
animArray = [];
|
||||
if ( throwDist < 600 && isLowThrowSafe() )
|
||||
{
|
||||
if ( throwDist < 300 )
|
||||
{
|
||||
// really short range
|
||||
animArray[ 0 ] = %grenade_return_running_throw_forward;
|
||||
animArray[ 1 ] = %grenade_return_standing_throw_forward_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// long range
|
||||
animArray[ 0 ] = %grenade_return_running_throw_forward;
|
||||
animArray[ 1 ] = %grenade_return_standing_throw_overhand_forward;
|
||||
}
|
||||
}
|
||||
|
||||
if ( animArray.size == 0 )
|
||||
{
|
||||
// really long range or can't do low throw
|
||||
animArray[ 0 ] = %grenade_return_standing_throw_overhand_forward;
|
||||
}
|
||||
|
||||
assert( animArray.size );
|
||||
throwAnim = animArray[ randomint( animArray.size ) ];
|
||||
|
||||
/#
|
||||
if ( getdvar( "scr_grenadereturnanim" ) != "" )
|
||||
{
|
||||
val = getdvar( "scr_grenadereturnanim" );
|
||||
//if ( val == "kick1")
|
||||
// throwAnim = %grenade_return_running_kick_forward_1;
|
||||
//else if ( val == "kick2")
|
||||
// throwAnim = %grenade_return_running_kick_forward_2;
|
||||
//else
|
||||
if ( val == "throw1" )
|
||||
throwAnim = %grenade_return_running_throw_forward;
|
||||
else if ( val == "throw2" )
|
||||
throwAnim = %grenade_return_standing_throw_forward_1;
|
||||
//else if ( val == "throw3")
|
||||
// throwAnim = %grenade_return_standing_throw_forward_2;
|
||||
else if ( val == "throw4" )
|
||||
throwAnim = %grenade_return_standing_throw_overhand_forward;
|
||||
}
|
||||
#/
|
||||
|
||||
assert( isdefined( throwAnim ) );
|
||||
self setFlaggedAnimKnoballRestart( "throwanim", throwAnim, %body, 1, .3 );
|
||||
|
||||
hasPickup = ( animHasNotetrack( throwAnim, "grenade_left" ) || animHasNotetrack( throwAnim, "grenade_right" ) );
|
||||
if ( hasPickup )
|
||||
{
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "left" );
|
||||
self thread putWeaponBackInRightHand();
|
||||
|
||||
self thread notifyGrenadePickup( "throwanim", "grenade_left" );
|
||||
self thread notifyGrenadePickup( "throwanim", "grenade_right" );
|
||||
self waittill( "grenade_pickup" );
|
||||
self pickUpGrenade();
|
||||
|
||||
self animscripts\battleChatter_ai::evaluateAttackEvent( "grenade" );
|
||||
|
||||
self waittillmatch( "throwanim", "grenade_throw" );
|
||||
}
|
||||
else
|
||||
{
|
||||
// kick animations don't have pickup.
|
||||
self waittillmatch( "throwanim", "grenade_throw" );
|
||||
self pickUpGrenade();
|
||||
|
||||
self animscripts\battleChatter_ai::evaluateAttackEvent( "grenade" );
|
||||
}
|
||||
|
||||
if ( isDefined( self.grenade ) ) // it may have exploded and we may have magic bullet shield
|
||||
self throwGrenade();
|
||||
|
||||
// TODO: replace with a notetrack?
|
||||
wait 1;
|
||||
|
||||
if ( hasPickup )
|
||||
{
|
||||
self notify( "put_weapon_back_in_right_hand" );
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
}
|
||||
|
||||
isLowThrowSafe()
|
||||
{
|
||||
start = ( self.origin[ 0 ], self.origin[ 1 ], self.origin[ 2 ] + 20 );
|
||||
end = start + anglesToForward( self.angles ) * 50;
|
||||
|
||||
return sightTracePassed( start, end, false, undefined );
|
||||
}
|
||||
|
||||
putWeaponBackInRightHand()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "put_weapon_back_in_right_hand" );
|
||||
|
||||
self waittill( "killanimscript" );
|
||||
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
|
||||
notifyGrenadePickup( animFlag, notetrack )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "grenade_pickup" );
|
||||
|
||||
self waittillmatch( animFlag, notetrack );
|
||||
self notify( "grenade_pickup" );
|
||||
}
|
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;
|
||||
}
|
35
animscripts/init.gsc
Normal file
35
animscripts/init.gsc
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#include animscripts\init_common;
|
||||
|
||||
main()
|
||||
{
|
||||
prof_begin( "animscript_init" );
|
||||
|
||||
pre_first_init();
|
||||
firstInit();
|
||||
post_first_init();
|
||||
|
||||
prof_end( "animscript_init" );
|
||||
}
|
||||
|
||||
firstInit()
|
||||
{
|
||||
// Initialization that should happen once per level
|
||||
if ( isDefined( anim.NotFirstTime ) )// Use this to trigger the first init
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pre_anim_init();
|
||||
|
||||
animscripts\animset::init_anim_sets();
|
||||
animscripts\init_move_transitions::initMoveStartStopTransitions();
|
||||
|
||||
anim.lastGibTime = 0;
|
||||
anim.gibDelay = 3 * 1000; // 3 seconds
|
||||
anim.minGibs = 2;
|
||||
anim.maxGibs = 4;
|
||||
anim.totalGibs = RandomIntRange( anim.minGibs, anim.maxGibs );
|
||||
|
||||
post_anim_init();
|
||||
}
|
926
animscripts/init_common.gsc
Normal file
926
animscripts/init_common.gsc
Normal file
@ -0,0 +1,926 @@
|
||||
// Notes about scripts
|
||||
//=====================
|
||||
//
|
||||
// Anim variables
|
||||
// --------------
|
||||
// Anim variables keep track of what the character is doing with respect to his
|
||||
// animations. They know if he's standing, crouching, kneeling, walking, running, etc,
|
||||
// so that he can play appropriate transitions to get to the animation he wants.
|
||||
// anim_movement - "stop", "walk", "run"
|
||||
// anim_pose - "stand", "crouch", "prone", some others for pain poses.
|
||||
// I'm putting functions to do the basic animations to change these variables in
|
||||
// SetPoseMovement.gsc,
|
||||
//
|
||||
// Error Reporting
|
||||
// ---------------
|
||||
// To report a script error condition (similar to assert(0)), I assign a non-existent variable to
|
||||
// the variable homemade_error I use the name of the non-existent variable to try to explain the
|
||||
// error. For example:
|
||||
// homemade_error = Unexpected_anim_pose_value + self.a.pose;
|
||||
// I also have a kind of assert, called as follows:
|
||||
// [[anim.assertEX(condition, message_string);
|
||||
// If condition evaluates to 0, the assert fires, prints message_string and stops the server. Since
|
||||
// I don't have stack traces of any kind, the message string needs to say from where the assert was
|
||||
// called.
|
||||
|
||||
#include animscripts\Utility;
|
||||
#include maps\_utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
initWeapon( weapon )
|
||||
{
|
||||
self.weaponInfo[ weapon ] = spawnstruct();
|
||||
self.weaponInfo[ weapon ].position = "none";
|
||||
self.weaponInfo[ weapon ].hasClip = true;
|
||||
self.weaponInfo[ weapon ].recharges = ( weapon != "none" && WeaponAmmoRecharges( weapon ) );
|
||||
|
||||
if ( getWeaponClipModel( weapon ) != "" )
|
||||
self.weaponInfo[ weapon ].useClip = true;
|
||||
else
|
||||
self.weaponInfo[ weapon ].useClip = false;
|
||||
}
|
||||
|
||||
isWeaponInitialized( weapon )
|
||||
{
|
||||
return isDefined( self.weaponInfo[ weapon ] );
|
||||
}
|
||||
|
||||
// Persistent global aiming limits / tolerances
|
||||
setGlobalAimSettings()
|
||||
{
|
||||
anim.coverCrouchLeanPitch = 55;
|
||||
|
||||
// Used by 'Explosed' combat (combat scirpt)
|
||||
anim.aimYawDiffFarTolerance = 10;
|
||||
anim.aimYawDiffCloseDistSQ = 64 * 64;
|
||||
anim.aimYawDiffCloseTolerance = 45;
|
||||
anim.aimPitchDiffTolerance = 20;
|
||||
|
||||
// Used by LastStand (pain script)
|
||||
anim.painYawDiffFarTolerance = 25;
|
||||
anim.painYawDiffCloseDistSQ = anim.aimYawDiffCloseDistSQ;
|
||||
anim.painYawDiffCloseTolerance = anim.aimYawDiffCloseTolerance;
|
||||
anim.painPitchDiffTolerance = 30;
|
||||
|
||||
// Absolute maximum trackLoop angles after which the weights are reset to 0
|
||||
// These must be greater than the maximum possible aiming limit for all stances
|
||||
anim.maxAngleCheckYawDelta = 65;
|
||||
anim.maxAngleCheckPitchDelta = 65;
|
||||
}
|
||||
|
||||
everUsesSecondaryWeapon()
|
||||
{
|
||||
if ( isShotgun( self.secondaryweapon ) )
|
||||
return true;
|
||||
if ( weaponClass( self.primaryweapon ) == "rocketlauncher" )
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
pre_first_init()
|
||||
{
|
||||
self.a = spawnStruct();
|
||||
self.a.laserOn = false;
|
||||
self.primaryweapon = self.weapon;
|
||||
}
|
||||
|
||||
post_first_init()
|
||||
{
|
||||
if ( self.primaryweapon == "" )
|
||||
self.primaryweapon = "none";
|
||||
if ( self.secondaryweapon == "" )
|
||||
self.secondaryweapon = "none";
|
||||
if ( self.sidearm == "" )
|
||||
self.sidearm = "none";
|
||||
|
||||
self initWeapon( self.primaryweapon );
|
||||
self initWeapon( self.secondaryweapon );
|
||||
self initWeapon( self.sidearm );
|
||||
|
||||
// this will cause us to think we're using our sidearm when we're not. the aitype should not allow this.
|
||||
assertex( self.primaryweapon != self.sidearm || self.primaryweapon == "none", "AI \"" + self.classname + "\" with export " + self.export + " has both a sidearm and primaryweapon of \"" + self.primaryweapon + "\"." );
|
||||
assertex( self.secondaryweapon != self.sidearm || self.secondaryweapon == "none" || !self everUsesSecondaryWeapon(), "AI \"" + self.classname + "\" with export " + self.export + " has both a sidearm and secondaryweapon of \"" + self.primaryweapon + "\"." );
|
||||
|
||||
self setDefaultAimLimits();
|
||||
|
||||
self.a.weaponPos[ "left" ] = "none";
|
||||
self.a.weaponPos[ "right" ] = "none";
|
||||
self.a.weaponPos[ "chest" ] = "none";
|
||||
self.a.weaponPos[ "back" ] = "none";
|
||||
|
||||
self.a.weaponPosDropping[ "left" ] = "none";
|
||||
self.a.weaponPosDropping[ "right" ] = "none";
|
||||
self.a.weaponPosDropping[ "chest" ] = "none";
|
||||
self.a.weaponPosDropping[ "back" ] = "none";
|
||||
|
||||
self.lastWeapon = self.weapon;
|
||||
self.root_anim = %root;
|
||||
|
||||
self thread beginGrenadeTracking();
|
||||
|
||||
hasRocketLauncher = usingRocketLauncher();
|
||||
self.a.neverLean = hasRocketLauncher;
|
||||
if ( hasRocketLauncher )
|
||||
self thread animscripts\shared::rpgPlayerRepulsor();
|
||||
|
||||
// TODO: proper ammo tracking
|
||||
self.a.rockets = 3;
|
||||
self.a.rocketVisible = true;
|
||||
|
||||
// SetWeaponDist();
|
||||
|
||||
// Set initial states for poses
|
||||
self.a.pose = "stand";
|
||||
self.a.grenadeThrowPose = "stand";
|
||||
self.a.movement = "stop";
|
||||
self.a.state = "stop";
|
||||
self.a.special = "none";
|
||||
self.a.gunHand = "none"; // Initialize so that PutGunInHand works properly.
|
||||
self.a.PrevPutGunInHandTime = -1;
|
||||
self.dropWeapon = true;
|
||||
self.minExposedGrenadeDist = 750;
|
||||
|
||||
animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
|
||||
if ( isShotgun( self.secondaryweapon ) )
|
||||
animscripts\shared::placeWeaponOn( self.secondaryweapon, "back" );
|
||||
|
||||
self.a.needsToRechamber = 0;
|
||||
self.a.combatEndTime = gettime();
|
||||
self.a.lastEnemyTime = gettime();
|
||||
self.a.suppressingEnemy = false;
|
||||
self.a.disableLongDeath = !( self isBadGuy() );
|
||||
self.a.lookangle = 0;
|
||||
self.a.painTime = 0;
|
||||
self.a.lastShootTime = 0;
|
||||
self.a.nextGrenadeTryTime = 0;
|
||||
self.a.reactToBulletChance = 0.8;
|
||||
|
||||
if ( self.team != "allies" )
|
||||
{
|
||||
// only select allies have IR laser and beacon
|
||||
self.has_no_ir = true;
|
||||
}
|
||||
|
||||
self.a.postScriptFunc = undefined;
|
||||
self.a.stance = "stand";
|
||||
self.choosePoseFunc = animscripts\utility::choosePose;
|
||||
//self.a.state = "idle";
|
||||
|
||||
self._animActive = 0;
|
||||
self._lastAnimTime = 0;
|
||||
|
||||
self thread enemyNotify();
|
||||
|
||||
self.baseAccuracy = 1;
|
||||
self.a.missTime = 0;
|
||||
|
||||
self.a.nodeath = false;
|
||||
self.a.missTime = 0;
|
||||
self.a.missTimeDebounce = 0;
|
||||
self.a.disablePain = false;
|
||||
|
||||
self.accuracyStationaryMod = 1;
|
||||
self.chatInitialized = false;
|
||||
self.sightPosTime = 0;
|
||||
self.sightPosLeft = true;
|
||||
self.needRecalculateGoodShootPos = true;
|
||||
self.defaultTurnThreshold = 55;
|
||||
self.painPlaybackRate = 1.0;
|
||||
|
||||
self.a.nextStandingHitDying = false;
|
||||
|
||||
// Makes AI able to throw grenades at other AI.
|
||||
if ( !isdefined( self.script_forcegrenade ) )
|
||||
self.script_forcegrenade = 0;
|
||||
|
||||
/# self.a.lastDebugPrint = ""; #/
|
||||
|
||||
SetupUniqueAnims();
|
||||
|
||||
/# thread animscripts\utility::UpdateDebugInfo(); #/
|
||||
|
||||
self animscripts\weaponList::RefillClip(); // Start with a full clip.
|
||||
|
||||
// state tracking
|
||||
self.lastEnemySightTime = 0;// last time we saw our current enemy
|
||||
self.combatTime = 0;// how long we've been in / out of combat
|
||||
|
||||
self.suppressed = false;// if we're currently suppressed
|
||||
self.suppressedTime = 0;// how long we've been in / out of suppression
|
||||
|
||||
if ( self.team == "allies" )
|
||||
self.suppressionThreshold = 0.5;
|
||||
else
|
||||
self.suppressionThreshold = 0.0;
|
||||
|
||||
// Random range makes the grenades less accurate and do less damage, but also makes it difficult to throw back.
|
||||
if ( self.team == "allies" )
|
||||
self.randomGrenadeRange = 0;
|
||||
else
|
||||
self.randomGrenadeRange = 256;
|
||||
|
||||
self.ammoCheatInterval = 8000; // if out of ammo and it's been this long since last time, do an instant reload
|
||||
self.ammoCheatTime = 0;
|
||||
animscripts\init_common::set_animset_run_n_gun();
|
||||
|
||||
self.exception = [];
|
||||
|
||||
self.exception[ "corner" ] = 1;
|
||||
self.exception[ "cover_crouch" ] = 1;
|
||||
self.exception[ "stop" ] = 1;
|
||||
self.exception[ "stop_immediate" ] = 1;
|
||||
self.exception[ "move" ] = 1;
|
||||
self.exception[ "exposed" ] = 1;
|
||||
self.exception[ "corner_normal" ] = 1;
|
||||
|
||||
keys = getArrayKeys( self.exception );
|
||||
for ( i = 0; i < keys.size; i++ )
|
||||
{
|
||||
clear_exception( keys[ i ] );
|
||||
}
|
||||
|
||||
self.reacquire_state = 0;
|
||||
|
||||
self thread setNameAndRank_andAddToSquad();
|
||||
|
||||
self.shouldConserveAmmoTime = 0;
|
||||
|
||||
/#
|
||||
self thread printEyeOffsetFromNode();
|
||||
self thread showLikelyEnemyPathDir();
|
||||
#/
|
||||
|
||||
self thread monitorFlash();
|
||||
|
||||
self thread onDeath();
|
||||
}
|
||||
|
||||
weapons_with_ir( weapon )
|
||||
{
|
||||
weapons[ 0 ] = "m4_grenadier";
|
||||
weapons[ 1 ] = "m4_grunt";
|
||||
weapons[ 2 ] = "m4_silencer";
|
||||
weapons[ 3 ] = "m4m203";
|
||||
|
||||
if ( !isdefined( weapon ) )
|
||||
return false;
|
||||
|
||||
for ( i = 0 ; i < weapons.size ; i++ )
|
||||
{
|
||||
if ( issubstr( weapon, weapons[ i ] ) )
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/#
|
||||
printEyeOffsetFromNode()
|
||||
{
|
||||
self endon( "death" );
|
||||
while ( 1 )
|
||||
{
|
||||
if ( getdvarint( "scr_eyeoffset" ) == self getentnum() )
|
||||
{
|
||||
if ( isdefined( self.coverNode ) )
|
||||
{
|
||||
offset = self geteye() - self.coverNode.origin;
|
||||
forward = anglestoforward( self.coverNode.angles );
|
||||
right = anglestoright( self.coverNode.angles );
|
||||
trueoffset = ( vectordot( right, offset ), vectordot( forward, offset ), offset[ 2 ] );
|
||||
println( trueoffset );
|
||||
}
|
||||
}
|
||||
else
|
||||
wait 2;
|
||||
wait .1;
|
||||
}
|
||||
}
|
||||
|
||||
showLikelyEnemyPathDir()
|
||||
{
|
||||
self endon( "death" );
|
||||
setDvarIfUninitialized( "scr_showlikelyenemypathdir", "-1" );
|
||||
while ( 1 )
|
||||
{
|
||||
if ( getdvarint( "scr_showlikelyenemypathdir" ) == self getentnum() )
|
||||
{
|
||||
yaw = self.angles[ 1 ];
|
||||
dir = self getAnglesToLikelyEnemyPath();
|
||||
if ( isdefined( dir ) )
|
||||
yaw = dir[ 1 ];
|
||||
printpos = self.origin + ( 0, 0, 60 ) + anglestoforward( ( 0, yaw, 0 ) ) * 100;
|
||||
line( self.origin + ( 0, 0, 60 ), printpos );
|
||||
if ( isdefined( dir ) )
|
||||
print3d( printpos, "likelyEnemyPathDir: " + yaw, ( 1, 1, 1 ), 1, 0.5 );
|
||||
else
|
||||
print3d( printpos, "likelyEnemyPathDir: undefined", ( 1, 1, 1 ), 1, 0.5 );
|
||||
|
||||
wait .05;
|
||||
}
|
||||
else
|
||||
wait 2;
|
||||
}
|
||||
}
|
||||
#/
|
||||
|
||||
setNameAndRank_andAddToSquad()
|
||||
{
|
||||
self endon( "death" );
|
||||
if ( !isdefined( level._loadoutComplete ) )
|
||||
level waittill( "loadout complete" );
|
||||
|
||||
self maps\_names::get_name();
|
||||
|
||||
// Init BC location cache
|
||||
self.bc_last_get_location_time = 0;
|
||||
self.bc_cache_time = 0;
|
||||
self.bc_locations = [];
|
||||
|
||||
// needs to run after the name has been set since bcs changes self.voice from "multilingual"
|
||||
// to something more specific
|
||||
self thread animscripts\squadManager::addToSquad();// slooooow
|
||||
}
|
||||
|
||||
|
||||
// Debug thread to see when stances are being allowed
|
||||
PollAllowedStancesThread()
|
||||
{
|
||||
for ( ;; )
|
||||
{
|
||||
if ( self isStanceAllowed( "stand" ) )
|
||||
{
|
||||
line[ 0 ] = "stand allowed";
|
||||
color[ 0 ] = ( 0, 1, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
line[ 0 ] = "stand not allowed";
|
||||
color[ 0 ] = ( 1, 0, 0 );
|
||||
}
|
||||
if ( self isStanceAllowed( "crouch" ) )
|
||||
{
|
||||
line[ 1 ] = "crouch allowed";
|
||||
color[ 1 ] = ( 0, 1, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
line[ 1 ] = "crouch not allowed";
|
||||
color[ 1 ] = ( 1, 0, 0 );
|
||||
}
|
||||
if ( self isStanceAllowed( "prone" ) )
|
||||
{
|
||||
line[ 2 ] = "prone allowed";
|
||||
color[ 2 ] = ( 0, 1, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
line[ 2 ] = "prone not allowed";
|
||||
color[ 2 ] = ( 1, 0, 0 );
|
||||
}
|
||||
|
||||
|
||||
aboveHead = self getshootatpos() + ( 0, 0, 30 );
|
||||
offset = ( 0, 0, -10 );
|
||||
for ( i = 0 ; i < line.size ; i++ )
|
||||
{
|
||||
textPos = ( aboveHead[ 0 ] + ( offset[ 0 ] * i ), aboveHead[ 1 ] + ( offset[ 1 ] * i ), aboveHead[ 2 ] + ( offset[ 2 ] * i ) );
|
||||
print3d( textPos, line[ i ], color[ i ], 1, 0.75 ); // origin, text, RGB, alpha, scale
|
||||
}
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
SetupUniqueAnims()
|
||||
{
|
||||
if ( !isDefined( self.animplaybackrate ) || !isDefined( self.moveplaybackrate ) )
|
||||
{
|
||||
set_anim_playback_rate();
|
||||
}
|
||||
}
|
||||
|
||||
set_anim_playback_rate()
|
||||
{
|
||||
self.animplaybackrate = 0.9 + randomfloat( 0.2 );
|
||||
self.moveTransitionRate = 0.9 + randomfloat( 0.2 );
|
||||
self.moveplaybackrate = 1;
|
||||
self.sideStepRate = 1.35;
|
||||
}
|
||||
|
||||
|
||||
infiniteLoop( one, two, three, whatever )
|
||||
{
|
||||
anim waittill( "new exceptions" );
|
||||
}
|
||||
|
||||
empty( one, two, three, whatever )
|
||||
{
|
||||
}
|
||||
|
||||
enemyNotify()
|
||||
{
|
||||
self endon( "death" );
|
||||
if ( 1 ) return;
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "enemy" );
|
||||
if ( !isalive( self.enemy ) )
|
||||
continue;
|
||||
while ( isplayer( self.enemy ) )
|
||||
{
|
||||
if ( hasEnemySightPos() )
|
||||
level._lastPlayerSighted = gettime();
|
||||
wait( 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
initWindowTraverse()
|
||||
{
|
||||
// used to blend the traverse window_down smoothly at the end
|
||||
level._window_down_height[ 0 ] = -36.8552;
|
||||
level._window_down_height[ 1 ] = -27.0095;
|
||||
level._window_down_height[ 2 ] = -15.5981;
|
||||
level._window_down_height[ 3 ] = -4.37769;
|
||||
level._window_down_height[ 4 ] = 17.7776;
|
||||
level._window_down_height[ 5 ] = 59.8499;
|
||||
level._window_down_height[ 6 ] = 104.808;
|
||||
level._window_down_height[ 7 ] = 152.325;
|
||||
level._window_down_height[ 8 ] = 201.052;
|
||||
level._window_down_height[ 9 ] = 250.244;
|
||||
level._window_down_height[ 10 ] = 298.971;
|
||||
level._window_down_height[ 11 ] = 330.681;
|
||||
}
|
||||
|
||||
pre_anim_init()
|
||||
{
|
||||
anim.NotFirstTime = true;
|
||||
|
||||
anim.useFacialAnims = false;// remove me when facial anims are fixed
|
||||
|
||||
maps\_load::init_level_players();
|
||||
|
||||
level._player.invul = false;
|
||||
level._nextGrenadeDrop = randomint( 3 );
|
||||
level._lastPlayerSighted = 100;
|
||||
|
||||
anim.defaultException = animscripts\init_common::empty;
|
||||
|
||||
initDeveloperDvars();
|
||||
|
||||
setdvar( "scr_expDeathMayMoveCheck", "on" );
|
||||
|
||||
maps\_names::setup_names();
|
||||
|
||||
anim.animFlagNameIndex = 0;
|
||||
}
|
||||
|
||||
post_anim_init()
|
||||
{
|
||||
anim.combatMemoryTimeConst = 10000;
|
||||
anim.combatMemoryTimeRand = 6000;
|
||||
|
||||
initAdvanceToEnemy();
|
||||
|
||||
setEnv( "none" );
|
||||
|
||||
if ( !isdefined( anim.optionalStepEffectFunction ) )
|
||||
{
|
||||
anim.optionalStepEffectSmallFunction = animscripts\shared::playFootStepEffectSmall;
|
||||
anim.optionalStepEffectFunction = animscripts\shared::playFootStepEffect;
|
||||
}
|
||||
|
||||
if ( !isdefined( anim.optionalStepEffects ) )
|
||||
anim.optionalStepEffects = [];
|
||||
|
||||
if ( !isdefined( anim.optionalStepEffectsSmall ) )
|
||||
anim.optionalStepEffectsSmall = [];
|
||||
|
||||
|
||||
anim.shootEnemyWrapper_func = ::shootEnemyWrapper_shootNotify;
|
||||
|
||||
// scripted mode uses a special function. Faster to use a function pointer based on script than use an if statement in a popular loop.
|
||||
anim.fire_notetrack_functions[ "scripted" ] = animscripts\shared::fire_straight;
|
||||
anim.fire_notetrack_functions[ "custom" ] = animscripts\shared::fire_straight;
|
||||
anim.fire_notetrack_functions[ "cover_right" ] = animscripts\shared::shootNotetrack;
|
||||
anim.fire_notetrack_functions[ "cover_left" ] = animscripts\shared::shootNotetrack;
|
||||
anim.fire_notetrack_functions[ "cover_crouch" ] = animscripts\shared::shootNotetrack;
|
||||
anim.fire_notetrack_functions[ "cover_stand" ] = animscripts\shared::shootNotetrack;
|
||||
anim.fire_notetrack_functions[ "move" ] = animscripts\shared::shootNotetrack;
|
||||
|
||||
// string based array for notetracks
|
||||
animscripts\shared::registerNoteTracks();
|
||||
|
||||
/#
|
||||
setDvarIfUninitialized( "debug_delta", "off" );
|
||||
#/
|
||||
|
||||
if ( !isdefined( level._flag ) )
|
||||
common_scripts\utility::init_flags();
|
||||
|
||||
maps\_gameskill::setSkill();
|
||||
level._painAI = undefined;
|
||||
|
||||
animscripts\SetPoseMovement::InitPoseMovementFunctions();
|
||||
animscripts\face::InitLevelFace();
|
||||
|
||||
// probabilities of burst fire shots
|
||||
anim.burstFireNumShots = array( 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 5 );
|
||||
anim.fastBurstFireNumShots = array( 2, 3, 3, 3, 4, 4, 4, 5, 5 );
|
||||
anim.semiFireNumShots = array( 1, 2, 2, 3, 3, 4, 4, 4, 4, 5, 5, 5 );
|
||||
|
||||
anim.badPlaces = [];// queue for animscript badplaces
|
||||
anim.badPlaceInt = 0;// assigns unique names to animscript badplaces since we cant save a badplace as an entity
|
||||
|
||||
anim.player = getentarray( "player", "classname" )[ 0 ];
|
||||
|
||||
initBattlechatter();
|
||||
|
||||
initWindowTraverse();
|
||||
|
||||
animscripts\flashed::initFlashed();
|
||||
|
||||
animscripts\cqb::setupCQBPointsOfInterest();
|
||||
|
||||
initDeaths();
|
||||
|
||||
setGlobalAimSettings();
|
||||
|
||||
anim.lastCarExplosionTime = -100000;
|
||||
|
||||
setupRandomTable();
|
||||
|
||||
level._player thread watchReloading();
|
||||
|
||||
thread AITurnNotifies();
|
||||
}
|
||||
|
||||
|
||||
|
||||
initDeveloperDvars()
|
||||
{
|
||||
/#
|
||||
if ( getdebugdvar( "debug_noanimscripts" ) == "" )
|
||||
setdvar( "debug_noanimscripts", "off" );
|
||||
else if ( getdebugdvar( "debug_noanimscripts" ) == "on" )
|
||||
anim.defaultException = animscripts\init_common::infiniteLoop;
|
||||
|
||||
if ( getdebugdvar( "debug_grenadehand" ) == "" )
|
||||
setdvar( "debug_grenadehand", "off" );
|
||||
if ( getdebugdvar( "anim_dotshow" ) == "" )
|
||||
setdvar( "anim_dotshow", "-1" );
|
||||
if ( getdebugdvar( "anim_debug" ) == "" )
|
||||
setdvar( "anim_debug", "" );
|
||||
if ( getdebugdvar( "debug_misstime" ) == "" )
|
||||
setdvar( "debug_misstime", "" );
|
||||
#/
|
||||
}
|
||||
|
||||
initBattlechatter()
|
||||
{
|
||||
animscripts\squadmanager::init_squadManager();
|
||||
anim.player thread animscripts\squadManager::addPlayerToSquad();
|
||||
|
||||
animscripts\battleChatter::init_battleChatter();
|
||||
anim.player thread animscripts\battleChatter_ai::addToSystem();
|
||||
|
||||
anim thread animscripts\battleChatter::bcsDebugWaiter();
|
||||
}
|
||||
|
||||
initDeaths()
|
||||
{
|
||||
anim.numDeathsUntilCrawlingPain = randomintrange( 0, 15 );
|
||||
anim.numDeathsUntilCornerGrenadeDeath = randomintrange( 0, 10 );
|
||||
anim.nextCrawlingPainTime = gettime() + randomintrange( 0, 20000 );
|
||||
anim.nextCrawlingPainTimeFromLegDamage = gettime() + randomintrange( 0, 10000 );
|
||||
anim.nextCornerGrenadeDeathTime = gettime() + randomintrange( 0, 15000 );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
initAdvanceToEnemy()
|
||||
{
|
||||
// use team ID for now. Should be done per group of AI or something more specific
|
||||
level._lastAdvanceToEnemyTime = [];
|
||||
level._lastAdvanceToEnemyTime[ "axis" ] = 0;
|
||||
level._lastAdvanceToEnemyTime[ "allies" ] = 0;
|
||||
level._lastAdvanceToEnemyTime[ "team3" ] = 0;
|
||||
level._lastAdvanceToEnemyTime[ "neutral" ] = 0;
|
||||
|
||||
level._lastAdvanceToEnemyDest = [];
|
||||
level._lastAdvanceToEnemyDest[ "axis" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemyDest[ "allies" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemyDest[ "team3" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemyDest[ "neutral" ] = ( 0, 0, 0 );
|
||||
|
||||
level._lastAdvanceToEnemySrc = [];
|
||||
level._lastAdvanceToEnemySrc[ "axis" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemySrc[ "allies" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemySrc[ "team3" ] = ( 0, 0, 0 );
|
||||
level._lastAdvanceToEnemySrc[ "neutral" ] = ( 0, 0, 0 );
|
||||
|
||||
level._lastAdvanceToEnemyAttacker = [];
|
||||
|
||||
level._advanceToEnemyGroup = [];
|
||||
level._advanceToEnemyGroup[ "axis" ] = 0;
|
||||
level._advanceToEnemyGroup[ "allies" ] = 0;
|
||||
level._advanceToEnemyGroup[ "team3" ] = 0;
|
||||
level._advanceToEnemyGroup[ "neutral" ] = 0;
|
||||
|
||||
level._advanceToEnemyInterval = 30000; // how often AI will try to run directly to their enemy if the enemy is not visible
|
||||
level._advanceToEnemyGroupMax = 3; // group size for AI running to their enemy
|
||||
}
|
||||
|
||||
|
||||
AITurnNotifies()
|
||||
{
|
||||
numTurnsThisFrame = 0;
|
||||
maxAIPerFrame = 3;
|
||||
while ( 1 )
|
||||
{
|
||||
ai = getAIArray();
|
||||
if ( ai.size == 0 )
|
||||
{
|
||||
wait .05;
|
||||
numTurnsThisFrame = 0;
|
||||
continue;
|
||||
}
|
||||
for ( i = 0; i < ai.size; i++ )
|
||||
{
|
||||
if ( !isdefined( ai[ i ] ) )
|
||||
continue;
|
||||
ai[ i ] notify( "do_slow_things" );
|
||||
numTurnsThisFrame++ ;
|
||||
if ( numTurnsThisFrame == maxAIPerFrame )
|
||||
{
|
||||
wait .05;
|
||||
numTurnsThisFrame = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setNextPlayerGrenadeTime()
|
||||
{
|
||||
assert( isPlayer( self ) );
|
||||
waittillframeend;
|
||||
// might not be defined if maps\_load::main() wasn't called
|
||||
if ( isdefined( self.gs.playerGrenadeRangeTime ) )
|
||||
{
|
||||
maxTime = int( self.gs.playerGrenadeRangeTime * 0.7 );
|
||||
if ( maxTime < 1 )
|
||||
maxTime = 1;
|
||||
self.grenadeTimers[ "fraggrenade" ] = randomIntRange( 0, maxTime );
|
||||
self.grenadeTimers[ "flash_grenade" ] = randomIntRange( 0, maxTime );
|
||||
}
|
||||
if ( isdefined( self.gs.playerDoubleGrenadeTime ) )
|
||||
{
|
||||
maxTime = int( self.gs.playerDoubleGrenadeTime );
|
||||
minTime = int( maxTime / 2 );
|
||||
if ( maxTime <= minTime )
|
||||
maxTime = minTime + 1;
|
||||
self.grenadeTimers[ "double_grenade" ] = randomIntRange( minTime, maxTime );
|
||||
}
|
||||
}
|
||||
|
||||
beginGrenadeTracking()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "grenade_fire", grenade, weaponName );
|
||||
grenade thread grenade_earthQuake();
|
||||
}
|
||||
}
|
||||
|
||||
setupRandomTable()
|
||||
{
|
||||
// 60 is chosen because it is divisible by 1,2,3,4,5, and 6,
|
||||
// and it's also high enough to get some good randomness over different seed values
|
||||
anim.randomIntTableSize = 60;
|
||||
|
||||
// anim.randomIntTable is a permutation of integers 0 through anim.randomIntTableSize - 1
|
||||
anim.randomIntTable = [];
|
||||
for ( i = 0; i < anim.randomIntTableSize; i++ )
|
||||
anim.randomIntTable[ i ] = i;
|
||||
|
||||
for ( i = 0; i < anim.randomIntTableSize; i++ )
|
||||
{
|
||||
switchwith = randomint( anim.randomIntTableSize );
|
||||
temp = anim.randomIntTable[ i ];
|
||||
anim.randomIntTable[ i ] = anim.randomIntTable[ switchwith ];
|
||||
anim.randomIntTable[ switchwith ] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
onDeath()
|
||||
{
|
||||
self waittill( "death" );
|
||||
if ( !isdefined( self ) )
|
||||
{
|
||||
// we were deleted and we're not running the death script.
|
||||
// still safe to access our variables as a removed entity though:
|
||||
if ( isdefined( self.a.usingTurret ) )
|
||||
self.a.usingTurret delete();
|
||||
}
|
||||
}
|
||||
|
||||
init_animset_custom_stand( fireAnim, aimStraight, idleAnim, reloadAnim )
|
||||
{
|
||||
assert( isdefined( anim.animsets ) && isdefined( anim.animsets.defaultStand ) );
|
||||
|
||||
anim.initAnimSet = anim.animsets.defaultStand;
|
||||
|
||||
if ( isdefined( aimStraight ) )
|
||||
anim.initAnimSet[ "straight_level" ] = aimStraight;
|
||||
|
||||
if ( isdefined( fireAnim ) )
|
||||
{
|
||||
anim.initAnimSet[ "fire" ] = fireAnim;
|
||||
anim.initAnimSet[ "single" ] = array( fireAnim );
|
||||
set_animarray_custom_burst_and_semi_fire_stand( fireAnim );
|
||||
}
|
||||
|
||||
if ( isdefined( idleAnim ) )
|
||||
anim.initAnimSet[ "exposed_idle" ] = array( idleAnim );
|
||||
|
||||
if ( isdefined( reloadAnim ) )
|
||||
{
|
||||
anim.initAnimSet[ "reload" ] = array( reloadAnim );
|
||||
anim.initAnimSet[ "reload_crouchhide" ] = array( reloadAnim );
|
||||
}
|
||||
|
||||
self.combatStandAnims = anim.initAnimSet;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Crouch
|
||||
////////////////////////////////////////////
|
||||
|
||||
set_animarray_crouching()
|
||||
{
|
||||
if ( usingSidearm() )
|
||||
animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
|
||||
|
||||
if ( isdefined( self.combatCrouchAnims ) )
|
||||
{
|
||||
assert( isArray( self.combatCrouchAnims ) );
|
||||
self.a.array = self.combatCrouchAnims;
|
||||
}
|
||||
else if ( usingRocketLauncher() )
|
||||
{
|
||||
self.a.array = anim.animsets.rpgCrouch;
|
||||
}
|
||||
else if ( isdefined( self.weapon ) && weapon_pump_action_shotgun() )
|
||||
{
|
||||
self.a.array = anim.animsets.shotgunCrouch;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.array = anim.animsets.defaultCrouch;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Stand
|
||||
////////////////////////////////////////////
|
||||
|
||||
set_animarray_standing()
|
||||
{
|
||||
if ( usingSidearm() )
|
||||
{
|
||||
self.a.array = anim.animsets.pistolStand;
|
||||
}
|
||||
else if ( isdefined( self.combatStandAnims ) )
|
||||
{
|
||||
assert( isArray( self.combatStandAnims ) );
|
||||
self.a.array = self.combatStandAnims;
|
||||
}
|
||||
else if ( isdefined( self.heat ) )
|
||||
{
|
||||
self.a.array = anim.animsets.heatStand;
|
||||
}
|
||||
else if ( usingRocketLauncher() )
|
||||
{
|
||||
self.a.array = anim.animsets.rpgStand;
|
||||
}
|
||||
else if ( isdefined( self.weapon ) && weapon_pump_action_shotgun() )
|
||||
{
|
||||
self.a.array = anim.animsets.shotgunStand;
|
||||
}
|
||||
else if ( self isCQBWalking() )
|
||||
{
|
||||
if ( isdefined( self.combatStandCQBAnims ) )
|
||||
{
|
||||
assert( isArray( self.combatStandCQBAnims ) );
|
||||
self.a.array = self.combatStandCQBAnims;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.array = anim.animsets.cqbStand;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.array = anim.animsets.defaultStand;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Prone
|
||||
////////////////////////////////////////////
|
||||
|
||||
set_animarray_prone()
|
||||
{
|
||||
if ( usingSidearm() )
|
||||
animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
|
||||
|
||||
self.a.array = anim.animsets.defaultProne;
|
||||
}
|
||||
|
||||
MAX_RUN_N_GUN_ANGLE = 130;
|
||||
RUN_N_GUN_TRANSITION_POINT = 60 / MAX_RUN_N_GUN_ANGLE;
|
||||
|
||||
set_animset_run_n_gun()
|
||||
{
|
||||
self.maxRunNGunAngle = MAX_RUN_N_GUN_ANGLE;
|
||||
self.runNGunTransitionPoint = RUN_N_GUN_TRANSITION_POINT;
|
||||
self.runNGunIncrement = 0.3;
|
||||
|
||||
self.runNGunAnims = anim.runNGunAnims;
|
||||
}
|
||||
|
||||
|
||||
set_ambush_sidestep_anims()
|
||||
{
|
||||
assert( isdefined( self.a.moveAnimSet ) );
|
||||
|
||||
self.a.moveAnimSet = array_combine_keys( self.a.moveAnimSet, anim.moveAnimSet );
|
||||
}
|
||||
|
||||
|
||||
set_animarray_custom_burst_and_semi_fire_stand( fireAnim )
|
||||
{
|
||||
anim.initAnimSet[ "burst2" ] = fireAnim;
|
||||
anim.initAnimSet[ "burst3" ] = fireAnim;
|
||||
anim.initAnimSet[ "burst4" ] = fireAnim;
|
||||
anim.initAnimSet[ "burst5" ] = fireAnim;
|
||||
anim.initAnimSet[ "burst6" ] = fireAnim;
|
||||
|
||||
anim.initAnimSet[ "semi2" ] = fireAnim;
|
||||
anim.initAnimSet[ "semi3" ] = fireAnim;
|
||||
anim.initAnimSet[ "semi4" ] = fireAnim;
|
||||
anim.initAnimSet[ "semi5" ] = fireAnim;
|
||||
}
|
||||
|
||||
set_animset_complete_custom_stand( completeSet )
|
||||
{
|
||||
self.combatStandAnims = completeSet;
|
||||
}
|
||||
|
||||
|
||||
set_animset_complete_custom_crouch( completeSet )
|
||||
{
|
||||
self.combatCrouchAnims = completeSet;
|
||||
}
|
||||
|
||||
clear_custom_animset()
|
||||
{
|
||||
self.customMoveAnimSet = undefined;
|
||||
self.customIdleAnimSet = undefined;
|
||||
|
||||
self.combatStandAnims = undefined;
|
||||
self.combatCrouchAnims = undefined;
|
||||
self.combatStandCQBAnims = undefined;
|
||||
|
||||
self.customTurnAnimSet = undefined;
|
||||
|
||||
self.customAnimFunc = undefined;
|
||||
|
||||
self.customCoverEnterTrans = undefined;
|
||||
self.customCoverExitTrans = undefined;
|
||||
|
||||
self.customDeathAnimSet = undefined;
|
||||
|
||||
self.customPainAnimSet = undefined;
|
||||
}
|
||||
|
||||
addGrenadeThrowAnimOffset( throwAnim, offset )
|
||||
{
|
||||
if ( !isdefined( anim.grenadeThrowAnims ) )
|
||||
{
|
||||
anim.grenadeThrowAnims = [];
|
||||
anim.grenadeThrowOffsets = [];
|
||||
}
|
||||
|
||||
assert( anim.grenadeThrowAnims.size == anim.grenadeThrowOffsets.size );
|
||||
|
||||
index = anim.grenadeThrowAnims.size;
|
||||
anim.grenadeThrowAnims[ index ] = throwAnim;
|
||||
anim.grenadeThrowOffsets[ index ] = offset;
|
||||
}
|
950
animscripts/init_move_transitions.gsc
Normal file
950
animscripts/init_move_transitions.gsc
Normal file
@ -0,0 +1,950 @@
|
||||
#include animscripts\Utility;
|
||||
#include maps\_utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
init_move_transition_arrays()
|
||||
{
|
||||
if ( isdefined( anim.move_transition_arrays ) )
|
||||
return;
|
||||
|
||||
anim.move_transition_arrays = 1;
|
||||
|
||||
anim.coverTrans = [];
|
||||
anim.coverExit = [];
|
||||
anim.maxDirections = [];
|
||||
anim.excludeDir = [];
|
||||
|
||||
anim.traverseInfo = [];
|
||||
|
||||
anim.coverTransLongestDist = [];
|
||||
anim.coverTransDist = [];
|
||||
anim.coverExitDist = [];
|
||||
|
||||
// this is the distance moved to get around corner for 7, 8, 9 directions
|
||||
anim.coverExitPostDist = [];
|
||||
|
||||
// this is the distance moved to get around corner for 7, 8, 9 directions
|
||||
anim.coverTransPreDist = [];
|
||||
|
||||
anim.coverTransAngles = [];
|
||||
anim.coverExitAngles = [];
|
||||
|
||||
anim.coverExitSplit = [];
|
||||
anim.coverTransSplit = [];
|
||||
|
||||
anim.arrivalEndStance = [];
|
||||
}
|
||||
|
||||
|
||||
initMoveStartStopTransitions()
|
||||
{
|
||||
init_move_transition_arrays();
|
||||
|
||||
// TEMP, remove this flag
|
||||
level._newArrivals = true;
|
||||
|
||||
transTypes = [];
|
||||
transTypes[ 0 ] = "left";
|
||||
transTypes[ 1 ] = "right";
|
||||
transTypes[ 2 ] = "left_crouch";
|
||||
transTypes[ 3 ] = "right_crouch";
|
||||
transTypes[ 4 ] = "crouch";
|
||||
transTypes[ 5 ] = "stand";
|
||||
transTypes[ 6 ] = "exposed";
|
||||
transTypes[ 7 ] = "exposed_crouch";
|
||||
transTypes[ 8 ] = "stand_saw";
|
||||
transTypes[ 9 ] = "prone_saw";
|
||||
transTypes[ 10 ] = "crouch_saw";
|
||||
transTypes[ 11 ] = "wall_over_40";
|
||||
transTypes[ 12 ] = "right_cqb";
|
||||
transTypes[ 13 ] = "right_crouch_cqb";
|
||||
transTypes[ 14 ] = "left_cqb";
|
||||
transTypes[ 15 ] = "left_crouch_cqb";
|
||||
transTypes[ 16 ] = "exposed_cqb";
|
||||
transTypes[ 17 ] = "exposed_crouch_cqb";
|
||||
transTypes[ 18 ] = "heat";
|
||||
transTypes[ 19 ] = "heat_left";
|
||||
transTypes[ 20 ] = "heat_right";
|
||||
|
||||
|
||||
lastCoverTrans = 6;
|
||||
|
||||
// tagJW<NOTE>: Non-lunar movements do not use move transition notes
|
||||
// Moon_actor's main is called before load, so don't override these if they exist
|
||||
if ( !isdefined( anim.run_transition_notes ) )
|
||||
{
|
||||
anim.cqb_transition_notes = [];
|
||||
anim.cqb_transition_points = [];
|
||||
|
||||
anim.run_transition_notes = [];
|
||||
anim.run_transition_points = [];
|
||||
}
|
||||
|
||||
anim.approach_types = [];
|
||||
|
||||
anim.approach_types[ "Cover Left" ] = [];
|
||||
anim.approach_types[ "Cover Left" ][ "stand" ] = "left";
|
||||
anim.approach_types[ "Cover Left" ][ "crouch" ] = "left_crouch";
|
||||
anim.maxDirections[ "Cover Left" ] = 9;
|
||||
anim.excludeDir[ "Cover Left" ] = 9;
|
||||
|
||||
anim.approach_types[ "Cover Right" ] = [];
|
||||
anim.approach_types[ "Cover Right" ][ "stand" ] = "right";
|
||||
anim.approach_types[ "Cover Right" ][ "crouch" ] = "right_crouch";
|
||||
anim.maxDirections[ "Cover Right" ] = 9;
|
||||
anim.excludeDir[ "Cover Right" ] = 7;
|
||||
|
||||
anim.approach_types[ "Cover Crouch" ] = [];
|
||||
anim.approach_types[ "Cover Crouch" ][ "stand" ] = "crouch";
|
||||
anim.approach_types[ "Cover Crouch" ][ "crouch" ] = "crouch";
|
||||
anim.approach_types[ "Conceal Crouch" ] = anim.approach_types[ "Cover Crouch" ];
|
||||
anim.approach_types[ "Cover Crouch Window" ] = anim.approach_types[ "Cover Crouch" ];
|
||||
anim.maxDirections[ "Cover Crouch" ] = 6;
|
||||
anim.excludeDir[ "Cover Crouch" ] = -1;
|
||||
anim.maxDirections[ "Conceal Crouch" ] = 6;
|
||||
anim.excludeDir[ "Conceal Crouch" ] = -1;
|
||||
|
||||
anim.approach_types[ "Cover Stand" ] = [];
|
||||
anim.approach_types[ "Cover Stand" ][ "stand" ] = "stand";
|
||||
anim.approach_types[ "Cover Stand" ][ "crouch" ] = "stand";
|
||||
anim.approach_types[ "Conceal Stand" ] = anim.approach_types[ "Cover Stand" ];
|
||||
anim.maxDirections[ "Cover Stand" ] = 6;
|
||||
anim.excludeDir[ "Cover Stand" ] = -1;
|
||||
anim.maxDirections[ "Conceal Stand" ] = 6;
|
||||
anim.excludeDir[ "Conceal Stand" ] = -1;
|
||||
|
||||
anim.approach_types[ "Cover Prone" ] = [];
|
||||
anim.approach_types[ "Cover Prone" ][ "stand" ] = "exposed";
|
||||
anim.approach_types[ "Cover Prone" ][ "crouch" ] = "exposed";
|
||||
anim.approach_types[ "Conceal Prone" ] = anim.approach_types[ "Cover Prone" ];
|
||||
anim.excludeDir[ "Conceal Prone" ] = -1;
|
||||
|
||||
anim.approach_types[ "Path" ] = [];
|
||||
anim.approach_types[ "Path" ][ "stand" ] = "exposed";
|
||||
anim.approach_types[ "Path" ][ "crouch" ] = "exposed_crouch";
|
||||
anim.approach_types[ "Guard" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Ambush" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Scripted" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Custom" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Exposed" ] = anim.approach_types[ "Path" ];
|
||||
|
||||
anim.isCombatPathNode[ "Guard" ] = true;
|
||||
anim.isCombatPathNode[ "Ambush" ] = true;
|
||||
anim.isCombatPathNode[ "Exposed" ] = true;
|
||||
|
||||
// used by level script to orient AI in certain ways at a node
|
||||
anim.isCombatScriptNode[ "Guard" ] = true;
|
||||
anim.isCombatScriptNode[ "Exposed" ] = true;
|
||||
|
||||
// CORNER TRANSITIONS ANIMS
|
||||
// indicies indicate the keyboard numpad directions (8 is forward)
|
||||
// 7 8 9
|
||||
// 4 6 <- 5 is invalid
|
||||
// 1 2 3
|
||||
|
||||
/*************************************************
|
||||
* Entrance Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverTrans[ "right" ][ 1 ] = %corner_standR_trans_IN_1;
|
||||
anim.coverTrans[ "right" ][ 2 ] = %corner_standR_trans_IN_2;
|
||||
anim.coverTrans[ "right" ][ 3 ] = %corner_standR_trans_IN_3;
|
||||
anim.coverTrans[ "right" ][ 4 ] = %corner_standR_trans_IN_4;
|
||||
anim.coverTrans[ "right" ][ 6 ] = %corner_standR_trans_IN_6;
|
||||
//im.coverTrans[ "right" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right" ][ 8 ] = %corner_standR_trans_IN_8;
|
||||
anim.coverTrans[ "right" ][ 9 ] = %corner_standR_trans_IN_9;
|
||||
|
||||
anim.coverTrans[ "right_crouch" ][ 1 ] = %CornerCrR_trans_IN_ML;
|
||||
anim.coverTrans[ "right_crouch" ][ 2 ] = %CornerCrR_trans_IN_M;
|
||||
anim.coverTrans[ "right_crouch" ][ 3 ] = %CornerCrR_trans_IN_MR;
|
||||
anim.coverTrans[ "right_crouch" ][ 4 ] = %CornerCrR_trans_IN_L;
|
||||
anim.coverTrans[ "right_crouch" ][ 6 ] = %CornerCrR_trans_IN_R;
|
||||
//im.coverTrans[ "right_crouch" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_crouch" ][ 8 ] = %CornerCrR_trans_IN_F;
|
||||
anim.coverTrans[ "right_crouch" ][ 9 ] = %CornerCrR_trans_IN_MF;
|
||||
|
||||
anim.coverTrans[ "right_cqb" ][ 1 ] = %corner_standR_trans_CQB_IN_1;
|
||||
anim.coverTrans[ "right_cqb" ][ 2 ] = %corner_standR_trans_CQB_IN_2;
|
||||
anim.coverTrans[ "right_cqb" ][ 3 ] = %corner_standR_trans_CQB_IN_3;
|
||||
anim.coverTrans[ "right_cqb" ][ 4 ] = %corner_standR_trans_CQB_IN_4;
|
||||
anim.coverTrans[ "right_cqb" ][ 6 ] = %corner_standR_trans_CQB_IN_6;
|
||||
//im.coverTrans[ "right_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_cqb" ][ 8 ] = %corner_standR_trans_CQB_IN_8;
|
||||
anim.coverTrans[ "right_cqb" ][ 9 ] = %corner_standR_trans_CQB_IN_9;
|
||||
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 1 ] = %CornerCrR_CQB_trans_IN_1;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 2 ] = %CornerCrR_CQB_trans_IN_2;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 3 ] = %CornerCrR_CQB_trans_IN_3;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 4 ] = %CornerCrR_CQB_trans_IN_4;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 6 ] = %CornerCrR_CQB_trans_IN_6;
|
||||
//im.coverTrans[ "right_crouch_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 8 ] = %CornerCrR_CQB_trans_IN_8;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 9 ] = %CornerCrR_CQB_trans_IN_9;
|
||||
|
||||
anim.coverTrans[ "left" ][ 1 ] = %corner_standL_trans_IN_1;
|
||||
anim.coverTrans[ "left" ][ 2 ] = %corner_standL_trans_IN_2;
|
||||
anim.coverTrans[ "left" ][ 3 ] = %corner_standL_trans_IN_3;
|
||||
anim.coverTrans[ "left" ][ 4 ] = %corner_standL_trans_IN_4;
|
||||
anim.coverTrans[ "left" ][ 6 ] = %corner_standL_trans_IN_6;
|
||||
anim.coverTrans[ "left" ][ 7 ] = %corner_standL_trans_IN_7;
|
||||
anim.coverTrans[ "left" ][ 8 ] = %corner_standL_trans_IN_8;
|
||||
//im.coverTrans[ "left" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_crouch" ][ 1 ] = %CornerCrL_trans_IN_ML;
|
||||
anim.coverTrans[ "left_crouch" ][ 2 ] = %CornerCrL_trans_IN_M;
|
||||
anim.coverTrans[ "left_crouch" ][ 3 ] = %CornerCrL_trans_IN_MR;
|
||||
anim.coverTrans[ "left_crouch" ][ 4 ] = %CornerCrL_trans_IN_L;
|
||||
anim.coverTrans[ "left_crouch" ][ 6 ] = %CornerCrL_trans_IN_R;
|
||||
anim.coverTrans[ "left_crouch" ][ 7 ] = %CornerCrL_trans_IN_MF;
|
||||
anim.coverTrans[ "left_crouch" ][ 8 ] = %CornerCrL_trans_IN_F;
|
||||
//im.coverTrans[ "left_crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_cqb" ][ 1 ] = %corner_standL_trans_CQB_IN_1;
|
||||
anim.coverTrans[ "left_cqb" ][ 2 ] = %corner_standL_trans_CQB_IN_2;
|
||||
anim.coverTrans[ "left_cqb" ][ 3 ] = %corner_standL_trans_CQB_IN_3;
|
||||
anim.coverTrans[ "left_cqb" ][ 4 ] = %corner_standL_trans_CQB_IN_4;
|
||||
anim.coverTrans[ "left_cqb" ][ 6 ] = %corner_standL_trans_CQB_IN_6;
|
||||
anim.coverTrans[ "left_cqb" ][ 7 ] = %corner_standL_trans_CQB_IN_7;
|
||||
anim.coverTrans[ "left_cqb" ][ 8 ] = %corner_standL_trans_CQB_IN_8;
|
||||
//im.coverTrans[ "left_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 1 ] = %CornerCrL_CQB_trans_IN_1;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 2 ] = %CornerCrL_CQB_trans_IN_2;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 3 ] = %CornerCrL_CQB_trans_IN_3;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 4 ] = %CornerCrL_CQB_trans_IN_4;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 6 ] = %CornerCrL_CQB_trans_IN_6;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 7 ] = %CornerCrL_CQB_trans_IN_7;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 8 ] = %CornerCrL_CQB_trans_IN_8;
|
||||
//im.coverTrans[ "left_crouch_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "crouch" ][ 1 ] = %covercrouch_run_in_ML;
|
||||
anim.coverTrans[ "crouch" ][ 2 ] = %covercrouch_run_in_M;
|
||||
anim.coverTrans[ "crouch" ][ 3 ] = %covercrouch_run_in_MR;
|
||||
anim.coverTrans[ "crouch" ][ 4 ] = %covercrouch_run_in_L;
|
||||
anim.coverTrans[ "crouch" ][ 6 ] = %covercrouch_run_in_R;
|
||||
//im.coverTrans[ "crouch" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "crouch" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "stand" ][ 1 ] = %coverstand_trans_IN_ML;
|
||||
anim.coverTrans[ "stand" ][ 2 ] = %coverstand_trans_IN_M;
|
||||
anim.coverTrans[ "stand" ][ 3 ] = %coverstand_trans_IN_MR;
|
||||
anim.coverTrans[ "stand" ][ 4 ] = %coverstand_trans_IN_L;
|
||||
anim.coverTrans[ "stand" ][ 6 ] = %coverstand_trans_IN_R;
|
||||
//im.coverTrans[ "stand" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "stand" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "stand" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "stand_saw" ][ 1 ] = %saw_gunner_runin_ML;
|
||||
anim.coverTrans[ "stand_saw" ][ 2 ] = %saw_gunner_runin_M;
|
||||
anim.coverTrans[ "stand_saw" ][ 3 ] = %saw_gunner_runin_MR;
|
||||
anim.coverTrans[ "stand_saw" ][ 4 ] = %saw_gunner_runin_L;
|
||||
anim.coverTrans[ "stand_saw" ][ 6 ] = %saw_gunner_runin_R;
|
||||
|
||||
anim.coverTrans[ "crouch_saw" ][ 1 ] = %saw_gunner_lowwall_runin_ML;
|
||||
anim.coverTrans[ "crouch_saw" ][ 2 ] = %saw_gunner_lowwall_runin_M;
|
||||
anim.coverTrans[ "crouch_saw" ][ 3 ] = %saw_gunner_lowwall_runin_MR;
|
||||
anim.coverTrans[ "crouch_saw" ][ 4 ] = %saw_gunner_lowwall_runin_L;
|
||||
anim.coverTrans[ "crouch_saw" ][ 6 ] = %saw_gunner_lowwall_runin_R;
|
||||
|
||||
anim.coverTrans[ "prone_saw" ][ 1 ] = %saw_gunner_prone_runin_ML;
|
||||
anim.coverTrans[ "prone_saw" ][ 2 ] = %saw_gunner_prone_runin_M;
|
||||
anim.coverTrans[ "prone_saw" ][ 3 ] = %saw_gunner_prone_runin_MR;
|
||||
|
||||
// we need 45 degree angle approaches for exposed...
|
||||
anim.coverTrans[ "exposed" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed" ][ 1 ] = %CQB_stop_1;
|
||||
anim.coverTrans[ "exposed" ][ 2 ] = %run_2_stand_F_6;
|
||||
anim.coverTrans[ "exposed" ][ 3 ] = %CQB_stop_3;
|
||||
anim.coverTrans[ "exposed" ][ 4 ] = %run_2_stand_90L;
|
||||
anim.coverTrans[ "exposed" ][ 6 ] = %run_2_stand_90R;
|
||||
anim.coverTrans[ "exposed" ][ 7 ] = %CQB_stop_7;
|
||||
anim.coverTrans[ "exposed" ][ 8 ] = %run_2_stand_180L;
|
||||
anim.coverTrans[ "exposed" ][ 9 ] = %CQB_stop_9;
|
||||
|
||||
anim.coverTrans[ "exposed_crouch" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_crouch" ][ 1 ] = %CQB_crouch_stop_1;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 2 ] = %run_2_crouch_F;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 3 ] = %CQB_crouch_stop_3;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 4 ] = %run_2_crouch_90L;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 6 ] = %run_2_crouch_90R;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 7 ] = %CQB_crouch_stop_7;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 8 ] = %run_2_crouch_180L;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 9 ] = %CQB_crouch_stop_9;
|
||||
|
||||
anim.coverTrans[ "exposed_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_cqb" ][ 1 ] = %CQB_stop_1;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 2 ] = %CQB_stop_2; // %CQB_stop_2_signal
|
||||
anim.coverTrans[ "exposed_cqb" ][ 3 ] = %CQB_stop_3;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 4 ] = %CQB_stop_4;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 6 ] = %CQB_stop_6;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 7 ] = %CQB_stop_7;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 8 ] = %CQB_stop_8;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 9 ] = %CQB_stop_9;
|
||||
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 1 ] = %CQB_crouch_stop_1;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 2 ] = %CQB_crouch_stop_2;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 3 ] = %CQB_crouch_stop_3;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 4 ] = %CQB_crouch_stop_4;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 6 ] = %CQB_crouch_stop_6;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 7 ] = %CQB_crouch_stop_7;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 8 ] = %CQB_crouch_stop_8;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 9 ] = %CQB_crouch_stop_9;
|
||||
|
||||
anim.coverTrans[ "heat" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "heat" ][ 1 ] = %heat_approach_1;
|
||||
anim.coverTrans[ "heat" ][ 2 ] = %heat_approach_2;
|
||||
anim.coverTrans[ "heat" ][ 3 ] = %heat_approach_3;
|
||||
anim.coverTrans[ "heat" ][ 4 ] = %heat_approach_4;
|
||||
anim.coverTrans[ "heat" ][ 6 ] = %heat_approach_6;
|
||||
//anim.coverTrans[ "heat" ][ 7 ] = %heat_approach_8;
|
||||
anim.coverTrans[ "heat" ][ 8 ] = %heat_approach_8;
|
||||
//anim.coverTrans[ "heat" ][ 9 ] = %heat_approach_8;
|
||||
|
||||
anim.coverTrans[ "heat_left" ] = [];
|
||||
anim.coverTrans[ "heat_right" ] = [];
|
||||
|
||||
/*************************************************
|
||||
* Step in position Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverStepInAnim = [];
|
||||
anim.coverStepInAnim[ "right" ] = %corner_standR_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "right_crouch" ] = %CornerCrR_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "left" ] = %corner_standL_trans_B_2_alert_v2;
|
||||
anim.coverStepInAnim[ "left_crouch" ] = %CornerCrL_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "crouch" ] = %covercrouch_aim_2_hide;
|
||||
anim.coverStepInAnim[ "stand" ] = %coverstand_aim_2_hide;
|
||||
|
||||
anim.coverStepInOffsets = [];
|
||||
anim.coverStepInAngles = [];
|
||||
|
||||
for( i = 0; i < lastCoverTrans; i++ )
|
||||
{
|
||||
trans = transTypes[i];
|
||||
anim.coverStepInOffsets[ trans ] = getMoveDelta( anim.coverStepInAnim[ trans ], 0, 1 );
|
||||
anim.coverStepInAngles[ trans ] = getAngleDelta( anim.coverStepInAnim[ trans ], 0, 1 );
|
||||
}
|
||||
|
||||
anim.coverStepInAngles[ "right" ] += 90;
|
||||
anim.coverStepInAngles[ "right_crouch" ] += 90;
|
||||
anim.coverStepInAngles[ "left" ] -= 90;
|
||||
anim.coverStepInAngles[ "left_crouch" ] -= 90;
|
||||
|
||||
/*************************************************
|
||||
* Traverse Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverTrans[ "wall_over_96" ][ 1 ] = %traverse90_IN_ML;
|
||||
anim.coverTrans[ "wall_over_96" ][ 2 ] = %traverse90_IN_M;
|
||||
anim.coverTrans[ "wall_over_96" ][ 3 ] = %traverse90_IN_MR;
|
||||
anim.traverseInfo[ "wall_over_96" ][ "height" ] = 96;
|
||||
|
||||
anim.coverTrans[ "wall_over_40" ][ 1 ] = %traverse_window_M_2_run;
|
||||
anim.coverTrans[ "wall_over_40" ][ 2 ] = %traverse_window_M_2_run;
|
||||
anim.coverTrans[ "wall_over_40" ][ 3 ] = %traverse_window_M_2_run;
|
||||
|
||||
/*
|
||||
anim.coverTrans["wall_over_40"][1] = %traverse40_IN_ML;
|
||||
anim.coverTrans["wall_over_40"][2] = %traverse40_IN_M;
|
||||
anim.coverTrans["wall_over_40"][3] = %traverse40_IN_MR;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Exit Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverExit[ "right" ][ 1 ] = %corner_standR_trans_OUT_1;
|
||||
anim.coverExit[ "right" ][ 2 ] = %corner_standR_trans_OUT_2;
|
||||
anim.coverExit[ "right" ][ 3 ] = %corner_standR_trans_OUT_3;
|
||||
anim.coverExit[ "right" ][ 4 ] = %corner_standR_trans_OUT_4;
|
||||
anim.coverExit[ "right" ][ 6 ] = %corner_standR_trans_OUT_6;
|
||||
//im.coverExit[ "right" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right" ][ 8 ] = %corner_standR_trans_OUT_8;
|
||||
anim.coverExit[ "right" ][ 9 ] = %corner_standR_trans_OUT_9;
|
||||
|
||||
anim.coverExit[ "right_crouch" ][ 1 ] = %CornerCrR_trans_OUT_ML;
|
||||
anim.coverExit[ "right_crouch" ][ 2 ] = %CornerCrR_trans_OUT_M;
|
||||
anim.coverExit[ "right_crouch" ][ 3 ] = %CornerCrR_trans_OUT_MR;
|
||||
anim.coverExit[ "right_crouch" ][ 4 ] = %CornerCrR_trans_OUT_L;
|
||||
anim.coverExit[ "right_crouch" ][ 6 ] = %CornerCrR_trans_OUT_R;
|
||||
//im.coverExit[ "right_crouch" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_crouch" ][ 8 ] = %CornerCrR_trans_OUT_F;
|
||||
anim.coverExit[ "right_crouch" ][ 9 ] = %CornerCrR_trans_OUT_MF;
|
||||
|
||||
anim.coverExit[ "right_cqb" ][ 1 ] = %corner_standR_trans_CQB_OUT_1;
|
||||
anim.coverExit[ "right_cqb" ][ 2 ] = %corner_standR_trans_CQB_OUT_2;
|
||||
anim.coverExit[ "right_cqb" ][ 3 ] = %corner_standR_trans_CQB_OUT_3;
|
||||
anim.coverExit[ "right_cqb" ][ 4 ] = %corner_standR_trans_CQB_OUT_4;
|
||||
anim.coverExit[ "right_cqb" ][ 6 ] = %corner_standR_trans_CQB_OUT_6;
|
||||
//im.coverExit[ "right_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_cqb" ][ 8 ] = %corner_standR_trans_CQB_OUT_8;
|
||||
anim.coverExit[ "right_cqb" ][ 9 ] = %corner_standR_trans_CQB_OUT_9;
|
||||
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 1 ] = %CornerCrR_CQB_trans_OUT_1;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 2 ] = %CornerCrR_CQB_trans_OUT_2;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 3 ] = %CornerCrR_CQB_trans_OUT_3;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 4 ] = %CornerCrR_CQB_trans_OUT_4;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 6 ] = %CornerCrR_CQB_trans_OUT_6;
|
||||
//im.coverExit[ "right_crouch_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 8 ] = %CornerCrR_CQB_trans_OUT_8;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 9 ] = %CornerCrR_CQB_trans_OUT_9;
|
||||
|
||||
|
||||
anim.coverExit[ "left" ][ 1 ] = %corner_standL_trans_OUT_1;
|
||||
anim.coverExit[ "left" ][ 2 ] = %corner_standL_trans_OUT_2;
|
||||
anim.coverExit[ "left" ][ 3 ] = %corner_standL_trans_OUT_3;
|
||||
anim.coverExit[ "left" ][ 4 ] = %corner_standL_trans_OUT_4;
|
||||
anim.coverExit[ "left" ][ 6 ] = %corner_standL_trans_OUT_6;
|
||||
anim.coverExit[ "left" ][ 7 ] = %corner_standL_trans_OUT_7;
|
||||
anim.coverExit[ "left" ][ 8 ] = %corner_standL_trans_OUT_8;
|
||||
//im.coverExit[ "left" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_crouch" ][ 1 ] = %CornerCrL_trans_OUT_ML;
|
||||
anim.coverExit[ "left_crouch" ][ 2 ] = %CornerCrL_trans_OUT_M;
|
||||
anim.coverExit[ "left_crouch" ][ 3 ] = %CornerCrL_trans_OUT_MR;
|
||||
anim.coverExit[ "left_crouch" ][ 4 ] = %CornerCrL_trans_OUT_L;
|
||||
anim.coverExit[ "left_crouch" ][ 6 ] = %CornerCrL_trans_OUT_R;
|
||||
anim.coverExit[ "left_crouch" ][ 7 ] = %CornerCrL_trans_OUT_MF;
|
||||
anim.coverExit[ "left_crouch" ][ 8 ] = %CornerCrL_trans_OUT_F;
|
||||
//im.coverExit[ "left_crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_cqb" ][ 1 ] = %corner_standL_trans_CQB_OUT_1;
|
||||
anim.coverExit[ "left_cqb" ][ 2 ] = %corner_standL_trans_CQB_OUT_2;
|
||||
anim.coverExit[ "left_cqb" ][ 3 ] = %corner_standL_trans_CQB_OUT_3;
|
||||
anim.coverExit[ "left_cqb" ][ 4 ] = %corner_standL_trans_CQB_OUT_4;
|
||||
anim.coverExit[ "left_cqb" ][ 6 ] = %corner_standL_trans_CQB_OUT_6;
|
||||
anim.coverExit[ "left_cqb" ][ 7 ] = %corner_standL_trans_CQB_OUT_7;
|
||||
anim.coverExit[ "left_cqb" ][ 8 ] = %corner_standL_trans_CQB_OUT_8;
|
||||
//im.coverExit[ "left_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 1 ] = %CornerCrL_CQB_trans_OUT_1;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 2 ] = %CornerCrL_CQB_trans_OUT_2;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 3 ] = %CornerCrL_CQB_trans_OUT_3;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 4 ] = %CornerCrL_CQB_trans_OUT_4;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 6 ] = %CornerCrL_CQB_trans_OUT_6;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 7 ] = %CornerCrL_CQB_trans_OUT_7;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 8 ] = %CornerCrL_CQB_trans_OUT_8;
|
||||
//im.coverExit[ "left_crouch_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "crouch" ][ 1 ] = %covercrouch_run_out_ML;
|
||||
anim.coverExit[ "crouch" ][ 2 ] = %covercrouch_run_out_M;
|
||||
anim.coverExit[ "crouch" ][ 3 ] = %covercrouch_run_out_MR;
|
||||
anim.coverExit[ "crouch" ][ 4 ] = %covercrouch_run_out_L;
|
||||
anim.coverExit[ "crouch" ][ 6 ] = %covercrouch_run_out_R;
|
||||
//im.coverExit[ "crouch" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverExit[ "crouch" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverExit[ "crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "stand" ][ 1 ] = %coverstand_trans_OUT_ML;
|
||||
anim.coverExit[ "stand" ][ 2 ] = %coverstand_trans_OUT_M;
|
||||
anim.coverExit[ "stand" ][ 3 ] = %coverstand_trans_OUT_MR;
|
||||
anim.coverExit[ "stand" ][ 4 ] = %coverstand_trans_OUT_L;
|
||||
anim.coverExit[ "stand" ][ 6 ] = %coverstand_trans_OUT_R;
|
||||
//im.coverExit[ "stand" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverExit[ "stand" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverExit[ "stand" ][ 9 ] = can't approach from this direction;
|
||||
anim.coverExit[ "stand_saw" ][ 1 ] = %saw_gunner_runout_ML;
|
||||
anim.coverExit[ "stand_saw" ][ 2 ] = %saw_gunner_runout_M;
|
||||
anim.coverExit[ "stand_saw" ][ 3 ] = %saw_gunner_runout_MR;
|
||||
anim.coverExit[ "stand_saw" ][ 4 ] = %saw_gunner_runout_L;
|
||||
anim.coverExit[ "stand_saw" ][ 6 ] = %saw_gunner_runout_R;
|
||||
|
||||
// anim.coverExit["prone_saw" ][1] = %saw_gunner_prone_runout_ML;
|
||||
anim.coverExit[ "prone_saw" ][ 2 ] = %saw_gunner_prone_runout_M;
|
||||
// anim.coverExit["prone_saw" ][3] = %saw_gunner_prone_runout_MR;
|
||||
anim.coverExit[ "prone_saw" ][ 4 ] = %saw_gunner_prone_runout_L;
|
||||
anim.coverExit[ "prone_saw" ][ 6 ] = %saw_gunner_prone_runout_R;
|
||||
// anim.coverExit["prone_saw" ][7] = %saw_gunner_prone_runout_F; // need this anim or a way to exclude it
|
||||
anim.coverExit[ "prone_saw" ][ 8 ] = %saw_gunner_prone_runout_F;
|
||||
|
||||
anim.coverExit[ "crouch_saw" ][ 1 ] = %saw_gunner_lowwall_runout_ML;
|
||||
anim.coverExit[ "crouch_saw" ][ 2 ] = %saw_gunner_lowwall_runout_M;
|
||||
anim.coverExit[ "crouch_saw" ][ 3 ] = %saw_gunner_lowwall_runout_MR;
|
||||
anim.coverExit[ "crouch_saw" ][ 4 ] = %saw_gunner_lowwall_runout_L;
|
||||
anim.coverExit[ "crouch_saw" ][ 6 ] = %saw_gunner_lowwall_runout_R;
|
||||
|
||||
// we need 45 degree angle exits for exposed...
|
||||
anim.coverExit[ "exposed" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed" ][ 1 ] = %CQB_start_1;
|
||||
anim.coverExit[ "exposed" ][ 2 ] = %stand_2_run_180L;
|
||||
anim.coverExit[ "exposed" ][ 3 ] = %CQB_start_3;
|
||||
anim.coverExit[ "exposed" ][ 4 ] = %stand_2_run_L;
|
||||
anim.coverExit[ "exposed" ][ 6 ] = %stand_2_run_R;
|
||||
anim.coverExit[ "exposed" ][ 7 ] = %CQB_start_7;
|
||||
anim.coverExit[ "exposed" ][ 8 ] = %surprise_start_v1; // %stand_2_run_F_2;
|
||||
anim.coverExit[ "exposed" ][ 9 ] = %CQB_start_9;
|
||||
|
||||
anim.coverExit[ "exposed_crouch" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_crouch" ][ 1 ] = %CQB_crouch_start_1;
|
||||
anim.coverExit[ "exposed_crouch" ][ 2 ] = %crouch_2run_180;
|
||||
anim.coverExit[ "exposed_crouch" ][ 3 ] = %CQB_crouch_start_3;
|
||||
anim.coverExit[ "exposed_crouch" ][ 4 ] = %crouch_2run_L;
|
||||
anim.coverExit[ "exposed_crouch" ][ 6 ] = %crouch_2run_R;
|
||||
anim.coverExit[ "exposed_crouch" ][ 7 ] = %CQB_crouch_start_7;
|
||||
anim.coverExit[ "exposed_crouch" ][ 8 ] = %crouch_2run_F;
|
||||
anim.coverExit[ "exposed_crouch" ][ 9 ] = %CQB_crouch_start_9;
|
||||
|
||||
anim.coverExit[ "exposed_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_cqb" ][ 1 ] = %CQB_start_1;
|
||||
anim.coverExit[ "exposed_cqb" ][ 2 ] = %CQB_start_2;
|
||||
anim.coverExit[ "exposed_cqb" ][ 3 ] = %CQB_start_3;
|
||||
anim.coverExit[ "exposed_cqb" ][ 4 ] = %CQB_start_4;
|
||||
anim.coverExit[ "exposed_cqb" ][ 6 ] = %CQB_start_6;
|
||||
anim.coverExit[ "exposed_cqb" ][ 7 ] = %CQB_start_7;
|
||||
anim.coverExit[ "exposed_cqb" ][ 8 ] = %CQB_start_8;
|
||||
anim.coverExit[ "exposed_cqb" ][ 9 ] = %CQB_start_9;
|
||||
|
||||
anim.coverExit[ "exposed_crouch_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 1 ] = %CQB_crouch_start_1;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 2 ] = %CQB_crouch_start_2;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 3 ] = %CQB_crouch_start_3;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 4 ] = %CQB_crouch_start_4;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 6 ] = %CQB_crouch_start_6;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 7 ] = %CQB_crouch_start_7;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 8 ] = %CQB_crouch_start_8;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 9 ] = %CQB_crouch_start_9;
|
||||
|
||||
anim.coverExit[ "heat" ] = [];
|
||||
anim.coverExit[ "heat" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat" ][ 6 ] = %heat_exit_6; //%heat_exit_6a
|
||||
anim.coverExit[ "heat" ][ 7 ] = %heat_exit_7;
|
||||
anim.coverExit[ "heat" ][ 8 ] = %heat_exit_8; //%heat_exit_8a
|
||||
anim.coverExit[ "heat" ][ 9 ] = %heat_exit_9;
|
||||
|
||||
anim.coverExit[ "heat_left" ] = [];
|
||||
anim.coverExit[ "heat_left" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat_left" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat_left" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat_left" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat_left" ][ 6 ] = %heat_exit_6;
|
||||
anim.coverExit[ "heat_left" ][ 7 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_left" ][ 8 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_left" ][ 9 ] = %heat_exit_8R;
|
||||
|
||||
anim.coverExit[ "heat_right" ] = [];
|
||||
anim.coverExit[ "heat_right" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat_right" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat_right" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat_right" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat_right" ][ 6 ] = %heat_exit_6;
|
||||
anim.coverExit[ "heat_right" ][ 7 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_right" ][ 8 ] = %heat_exit_8R;
|
||||
anim.coverExit[ "heat_right" ][ 9 ] = %heat_exit_8R;
|
||||
|
||||
|
||||
for ( i = 1; i <= 6; i++ )
|
||||
{
|
||||
if ( i == 5 )
|
||||
continue;
|
||||
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
if ( isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
{
|
||||
anim.coverTransDist [ trans ][ i ] = getMoveDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
anim.coverTransAngles[ trans ][ i ] = getAngleDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
if ( isdefined( anim.coverExit [ trans ] ) && isdefined( anim.coverExit [ trans ][ i ] ) )
|
||||
{
|
||||
// get exit dist only to code_move
|
||||
if ( animHasNotetrack( anim.coverExit[ trans ][ i ], "code_move" ) )
|
||||
codeMoveTime = getNotetrackTimes( anim.coverExit[ trans ][ i ], "code_move" )[ 0 ];
|
||||
else
|
||||
codeMoveTime = 1;
|
||||
|
||||
anim.coverExitDist [ trans ][ i ] = getMoveDelta( anim.coverExit [ trans ][ i ], 0, codeMoveTime );
|
||||
anim.coverExitAngles [ trans ][ i ] = getAngleDelta( anim.coverExit [ trans ][ i ], 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
anim.coverTransLongestDist[ trans ] = 0;
|
||||
|
||||
for ( i = 1; i <= 6; i++ )
|
||||
{
|
||||
if ( i == 5 || !isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
continue;
|
||||
|
||||
lengthSq = lengthSquared( anim.coverTransDist[ trans ][ i ] );
|
||||
if ( anim.coverTransLongestDist[ trans ] < lengthSq )
|
||||
anim.coverTransLongestDist[ trans ] = lengthSq;
|
||||
}
|
||||
|
||||
anim.coverTransLongestDist[ trans ] = sqrt( anim.coverTransLongestDist[ trans ] );
|
||||
}
|
||||
|
||||
anim.exposedTransition[ "exposed" ] = true;
|
||||
anim.exposedTransition[ "exposed_crouch" ] = true;
|
||||
anim.exposedTransition[ "exposed_cqb" ] = true;
|
||||
anim.exposedTransition[ "exposed_crouch_cqb" ] = true;
|
||||
anim.exposedTransition[ "heat" ] = true;
|
||||
|
||||
anim.longestExposedApproachDist = 0;
|
||||
|
||||
foreach ( trans, transType in anim.exposedTransition )
|
||||
{
|
||||
for ( i = 7; i <= 9; i++ )
|
||||
{
|
||||
if ( isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
{
|
||||
anim.coverTransDist [ trans ][ i ] = getMoveDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
anim.coverTransAngles[ trans ][ i ] = getAngleDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
if ( isdefined( anim.coverExit [ trans ][ i ] ) )
|
||||
{
|
||||
// get exit dist only to code_move
|
||||
assert( animHasNotetrack( anim.coverExit[ trans ][ i ], "code_move" ) );
|
||||
codeMoveTime = getNotetrackTimes( anim.coverExit[ trans ][ i ], "code_move" )[ 0 ];
|
||||
|
||||
anim.coverExitDist [ trans ][ i ] = getMoveDelta( anim.coverExit [ trans ][ i ], 0, codeMoveTime );
|
||||
anim.coverExitAngles [ trans ][ i ] = getAngleDelta( anim.coverExit [ trans ][ i ], 0, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
if ( !isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
continue;
|
||||
|
||||
len = length( anim.coverTransDist[ trans ][ i ] );
|
||||
if ( len > anim.longestExposedApproachDist )
|
||||
anim.longestExposedApproachDist = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the FindBestSplitTime calls below are used to find these values.
|
||||
// all of this is for corner nodes.
|
||||
|
||||
anim.coverTransSplit[ "left" ][ 7 ] = 0.369369;// delta of( 35.5356, 3.27114, 0 )
|
||||
anim.coverTransSplit[ "left_crouch" ][ 7 ] = 0.319319; // delta of (32.2281, 0.356673, 0)
|
||||
anim.coverTransSplit[ "left_cqb" ][ 7 ] = 0.451451; // delta of (33.1115, 1.05645, 0)
|
||||
anim.coverTransSplit[ "left_crouch_cqb" ][ 7 ] = 0.246246; // delta of (34.2986, 2.32586, 0)
|
||||
anim.coverExitSplit[ "left" ][ 7 ] = 0.547548;// delta of( 37.5652, 5.61999, 0 )
|
||||
anim.coverExitSplit[ "left_crouch" ][ 7 ] = 0.593594;// delta of( 35.9166, 3.88091, 0 )
|
||||
anim.coverExitSplit[ "left_cqb" ][ 7 ] = 0.702703; // delta of (32.9692, 0.881301, 0)
|
||||
anim.coverExitSplit[ "left_crouch_cqb" ][ 7 ] = 0.718719; // delta of (33.6642, 1.70904, 0)
|
||||
anim.coverExitSplit[ "heat_left" ][ 7 ] = 0.42;
|
||||
|
||||
anim.coverTransSplit[ "left" ][ 8 ] = 0.525526;// delta of( 32.9863, 0.925748, 0 )
|
||||
anim.coverTransSplit[ "left_crouch" ][ 8 ] = 0.428428;// delta of( 38.4125, 6.445, 0 )
|
||||
anim.coverTransSplit[ "left_cqb" ][ 8 ] = 0.479479; // delta of (33.892, 1.86121, 0)
|
||||
anim.coverTransSplit[ "left_crouch_cqb" ][ 8 ] = 0.33033; // delta of (35.8107, 3.70985, 0)
|
||||
anim.coverExitSplit[ "left" ][ 8 ] = 0.614615;// delta of( 34.298, 2.26239, 0 )
|
||||
anim.coverExitSplit[ "left_crouch" ][ 8 ] = 0.451451; // delta of (33.0388, 0.964628, 0)
|
||||
anim.coverExitSplit[ "left_cqb" ][ 8 ] = 0.439439; // delta of (35.6563, 3.64754, 0))
|
||||
anim.coverExitSplit[ "left_crouch_cqb" ][ 8 ] = 0.603604; // delta of (33.0797, 1.14774, 0)
|
||||
anim.coverExitSplit[ "heat_left" ][ 8 ] = 0.42;
|
||||
|
||||
anim.coverTransSplit[ "right" ][ 8 ] = 0.458458;// delta of( 35.6571, 3.63511, 0 )
|
||||
anim.coverTransSplit[ "right_crouch" ][ 8 ] = 0.248248; // delta of (34.6368, 2.67554, 0)
|
||||
anim.coverTransSplit[ "right_cqb" ][ 8 ] = 0.458458; // delta of (35.6571, 3.63511, 0)
|
||||
anim.coverTransSplit[ "right_crouch_cqb" ][ 8 ] = 0.311311; // delta of (34.2736, 2.32471, 0)
|
||||
anim.coverExitSplit[ "right" ][ 8 ] = 0.457457;// delta of( 36.3085, 4.34586, 0 )
|
||||
anim.coverExitSplit[ "right_crouch" ][ 8 ] = 0.545546; // delta of (33.1181, 1.14301, -0.0001)
|
||||
anim.coverExitSplit[ "right_cqb" ][ 8 ] = 0.540541; // delta of (33.0089, 1.0005, 0)
|
||||
anim.coverExitSplit[ "right_crouch_cqb" ][ 8 ] = 0.399399; // delta of (34.7739, 2.41176, 0)
|
||||
anim.coverExitSplit[ "heat_right" ][ 8 ] = 0.4;
|
||||
|
||||
anim.coverTransSplit[ "right" ][ 9 ] = 0.546547;// delta of( 37.7732, 5.76641, 0 )
|
||||
anim.coverTransSplit[ "right_crouch" ][ 9 ] = 0.2002; // delta of (36.3871, 4.39434, 0)
|
||||
anim.coverTransSplit[ "right_cqb" ][ 9 ] = 0.546547;// delta of( 37.7732, 5.76641, 0 )
|
||||
anim.coverTransSplit[ "right_crouch_cqb" ][ 9 ] = 0.232232; // delta of (35.8102, 3.81592, 0)
|
||||
anim.coverExitSplit[ "right" ][ 9 ] = 0.483483; // delta of (35.251, 3.31115, 0)
|
||||
anim.coverExitSplit[ "right_crouch" ][ 9 ] = 0.493493; // delta of (34.4959, 2.45688, -0.0001)
|
||||
anim.coverExitSplit[ "right_cqb" ][ 9 ] = 0.565566; // delta of (35.4487, 3.42926, 0)
|
||||
anim.coverExitSplit[ "right_crouch_cqb" ][ 9 ] = 0.518519; // delta of (35.4592, 1.47273, 0)
|
||||
anim.coverExitSplit[ "heat_right" ][ 9 ] = 0.4;
|
||||
|
||||
/#
|
||||
setDvarIfUninitialized( "scr_findsplittimes", "0" );
|
||||
#/
|
||||
|
||||
splitArrivals = [];
|
||||
splitArrivals[ "left" ] = 1;
|
||||
splitArrivals[ "left_crouch" ] = 1;
|
||||
splitArrivals[ "left_crouch_cqb" ] = 1;
|
||||
splitArrivals[ "left_cqb" ] = 1;
|
||||
|
||||
splitExits = [];
|
||||
splitExits[ "left" ] = 1;
|
||||
splitExits[ "left_crouch" ] = 1;
|
||||
splitExits[ "left_crouch_cqb" ] = 1;
|
||||
splitExits[ "left_cqb" ] = 1;
|
||||
splitExits[ "heat_left" ] = 1;
|
||||
|
||||
GetSplitTimes( 7, 8, false, splitArrivals, splitExits );
|
||||
|
||||
|
||||
splitArrivals = [];
|
||||
splitArrivals[ "right" ] = 1;
|
||||
splitArrivals[ "right_crouch" ] = 1;
|
||||
splitArrivals[ "right_cqb" ] = 1;
|
||||
splitArrivals[ "right_crouch_cqb" ] = 1;
|
||||
|
||||
splitExits = [];
|
||||
splitExits[ "right" ] = 1;
|
||||
splitExits[ "right_crouch" ] = 1;
|
||||
splitExits[ "right_cqb" ] = 1;
|
||||
splitExits[ "right_crouch_cqb" ] = 1;
|
||||
splitExits[ "heat_right" ] = 1;
|
||||
|
||||
GetSplitTimes( 8, 9, true, splitArrivals, splitExits );
|
||||
|
||||
|
||||
/#
|
||||
//thread checkApproachAngles( transTypes );
|
||||
#/
|
||||
|
||||
anim.arrivalEndStance["left"] = "stand";
|
||||
anim.arrivalEndStance["left_cqb"] = "stand";
|
||||
anim.arrivalEndStance["right"] = "stand";
|
||||
anim.arrivalEndStance["right_cqb"] = "stand";
|
||||
anim.arrivalEndStance["stand"] = "stand";
|
||||
anim.arrivalEndStance["stand_saw"] = "stand";
|
||||
anim.arrivalEndStance["exposed"] = "stand";
|
||||
anim.arrivalEndStance["exposed_cqb"] = "stand";
|
||||
anim.arrivalEndStance["heat"] = "stand";
|
||||
anim.arrivalEndStance["left_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["left_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["right_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["right_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["crouch_saw"] = "crouch";
|
||||
anim.arrivalEndStance["crouch"] = "crouch";
|
||||
anim.arrivalEndStance["exposed_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["exposed_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["prone_saw"] = "prone";
|
||||
|
||||
anim.requiredExitStance[ "Cover Stand" ] = "stand";
|
||||
anim.requiredExitStance[ "Conceal Stand" ] = "stand";
|
||||
anim.requiredExitStance[ "Cover Crouch" ] = "crouch";
|
||||
anim.requiredExitStance[ "Conceal Crouch" ] = "crouch";
|
||||
}
|
||||
|
||||
|
||||
GetSplitTimes( begin, end, isRightSide, splitArrivals, splitExits )
|
||||
{
|
||||
for ( i = begin; i <= end; i++ )
|
||||
{
|
||||
foreach ( type, val in splitArrivals )
|
||||
{
|
||||
anim.coverTransPreDist[ type ][ i ] = getMoveDelta( anim.coverTrans[ type ][ i ], 0, getTransSplitTime( type, i ) );
|
||||
anim.coverTransDist [ type ][ i ] = getMoveDelta( anim.coverTrans[ type ][ i ], 0, 1 ) - anim.coverTransPreDist[ type ][ i ];
|
||||
anim.coverTransAngles [ type ][ i ] = getAngleDelta( anim.coverTrans[ type ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
foreach ( type, val in splitExits )
|
||||
{
|
||||
anim.coverExitDist [ type ][ i ] = getMoveDelta( anim.coverExit [ type ][ i ], 0, getExitSplitTime( type, i ) );
|
||||
anim.coverExitPostDist[ type ][ i ] = getMoveDelta( anim.coverExit [ type ][ i ], 0, 1 ) - anim.coverExitDist[ type ][ i ];
|
||||
anim.coverExitAngles [ type ][ i ] = getAngleDelta( anim.coverExit [ type ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
/#
|
||||
if ( getdebugdvar( "scr_findsplittimes" ) != "0" )
|
||||
{
|
||||
foreach ( type, val in splitArrivals )
|
||||
{
|
||||
if ( isSubStr( type, "heat" ) )
|
||||
continue;
|
||||
|
||||
FindBestSplitTime( anim.coverTrans[ type ][ i ], true, isRightSide, "anim.coverTransSplit[ \"" + type + "\" ][ " + i + " ]", type + " arrival in dir " + i );
|
||||
AssertIsValidSplitDelta( DeltaRotate( anim.coverTransDist[ type ][ i ], 180 - anim.coverTransAngles[ type ][ i ] ), isRightSide, type + " arrival in dir " + i );
|
||||
}
|
||||
|
||||
foreach ( type, val in splitExits )
|
||||
{
|
||||
if ( isSubStr( type, "heat" ) )
|
||||
continue;
|
||||
|
||||
FindBestSplitTime( anim.coverExit [ type ][ i ], false, isRightSide, "anim.coverExitSplit[ \"" + type + "\" ][ " + i + " ]", type + " exit in dir " + i );
|
||||
AssertIsValidSplitDelta( anim.coverExitDist[ type ][ i ], isRightSide, type + " exit in dir " + i );
|
||||
}
|
||||
}
|
||||
#/
|
||||
}
|
||||
}
|
||||
|
||||
/#
|
||||
FindBestSplitTime( exitanim, isapproach, isright, arrayname, debugname )
|
||||
{
|
||||
angleDelta = getAngleDelta( exitanim, 0, 1 );
|
||||
fullDelta = getMoveDelta( exitanim, 0, 1 );
|
||||
numiter = 1000;
|
||||
|
||||
bestsplit = -1;
|
||||
bestvalue = -100000000;
|
||||
bestdelta = ( 0, 0, 0 );
|
||||
|
||||
for ( i = 0; i < numiter; i++ )
|
||||
{
|
||||
splitTime = 1.0 * i / ( numiter - 1 );
|
||||
|
||||
delta = getMoveDelta( exitanim, 0, splitTime );
|
||||
if ( isapproach )
|
||||
delta = DeltaRotate( fullDelta - delta, 180 - angleDelta );
|
||||
if ( isright )
|
||||
delta = ( delta[ 0 ], 0 - delta[ 1 ], delta[ 2 ] );
|
||||
|
||||
val = min( delta[ 0 ] - 32, delta[ 1 ] );
|
||||
|
||||
if ( val > bestvalue || bestsplit < 0 )
|
||||
{
|
||||
bestvalue = val;
|
||||
bestsplit = splitTime;
|
||||
bestdelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestdelta[ 0 ] < 32 || bestdelta[ 1 ] < 0 )
|
||||
{
|
||||
println( "^0 ^1" + debugname + " has no valid split time available! Best was at " + bestsplit + ", delta of " + bestdelta );
|
||||
return;
|
||||
}
|
||||
//println("^0 ^2" + debugname + " has best split time at " + bestsplit + ", delta of " + bestdelta );
|
||||
println( "^0 ^2" + arrayname + " = " + bestsplit + "; // delta of " + bestdelta );
|
||||
}
|
||||
|
||||
|
||||
DeltaRotate( delta, yaw )
|
||||
{
|
||||
cosine = cos( yaw );
|
||||
sine = sin( yaw );
|
||||
return( delta[ 0 ] * cosine - delta[ 1 ] * sine, delta[ 1 ] * cosine + delta[ 0 ] * sine, 0 );
|
||||
}
|
||||
|
||||
AssertIsValidSplitDelta( delta, isRightSide, debugname )
|
||||
{
|
||||
if ( isRightSide )
|
||||
delta = ( delta[ 0 ], 0 - delta[ 1 ], delta[ 2 ] );
|
||||
|
||||
// in a delta, x is forward and y is left
|
||||
|
||||
// assert the delta goes out far enough from the node
|
||||
if ( delta[ 0 ] < 32 )
|
||||
println( "^0 ^1" + debugname + " doesn't go out from the node far enough in the given split time (delta = " + delta + ")" );
|
||||
|
||||
// assert the delta doesn't go into the wall
|
||||
if ( delta[ 1 ] < 0 )
|
||||
println( "^0 ^1" + debugname + " goes into the wall during the given split time (delta = " + delta + ")" );
|
||||
}
|
||||
|
||||
checkApproachAngles( transTypes )
|
||||
{
|
||||
idealTransAngles[ 1 ] = 45;
|
||||
idealTransAngles[ 2 ] = 0;
|
||||
idealTransAngles[ 3 ] = -45;
|
||||
idealTransAngles[ 4 ] = 90;
|
||||
idealTransAngles[ 6 ] = -90;
|
||||
idealTransAngles[ 7 ] = 135;
|
||||
idealTransAngles[ 8 ] = 180;
|
||||
idealTransAngles[ 9 ] = -135;
|
||||
|
||||
wait .05;
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
idealAdd = 0;
|
||||
if ( trans == "left" || trans == "left_crouch" )
|
||||
idealAdd = 90;
|
||||
else if ( trans == "right" || trans == "right_crouch" )
|
||||
idealAdd = -90;
|
||||
|
||||
if ( isdefined( anim.coverTransAngles[ trans ][ i ] ) )
|
||||
{
|
||||
correctAngle = AngleClamp180( idealTransAngles[ i ] + idealAdd );
|
||||
actualAngle = AngleClamp180( anim.coverTransAngles[ trans ][ i ] );
|
||||
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
|
||||
{
|
||||
println( "^1Cover approach animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
idealAdd = 0;
|
||||
if ( trans == "left" || trans == "left_crouch" )
|
||||
idealAdd = 90;
|
||||
else if ( trans == "right" || trans == "right_crouch" )
|
||||
idealAdd = -90;
|
||||
|
||||
if ( isdefined( anim.coverExitAngles[ trans ][ i ] ) )
|
||||
{
|
||||
correctAngle = AngleClamp180( -1 * ( idealTransAngles[ i ] + idealAdd + 180 ) );
|
||||
actualAngle = AngleClamp180( anim.coverExitAngles[ trans ][ i ] );
|
||||
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
|
||||
{
|
||||
println( "^1Cover exit animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#/
|
||||
|
||||
getExitSplitTime( approachType, dir )
|
||||
{
|
||||
exitAnim = anim.coverExit[ approachType ][ dir ];
|
||||
if ( animHasNotetrack( exitAnim, "split_time" ) )
|
||||
{
|
||||
exitAlignTimes = getNotetrackTimes( exitAnim, "split_time" );
|
||||
|
||||
assert( exitAlignTimes.size == 1 );
|
||||
if ( exitAlignTimes.size == 0 )
|
||||
{
|
||||
return anim.coverExitSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
return exitAlignTimes[0];
|
||||
}
|
||||
|
||||
return anim.coverExitSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
getTransSplitTime( approachType, dir )
|
||||
{
|
||||
arrivalAnim = anim.coverTrans[ approachType ][ dir ];
|
||||
if ( animHasNotetrack( arrivalAnim, "split_time" ) )
|
||||
{
|
||||
arrivalSplitTimes = getNotetrackTimes( arrivalAnim, "split_time" );
|
||||
|
||||
assert( arrivalSplitTimes.size == 1 );
|
||||
if ( arrivalSplitTimes.size == 0 )
|
||||
{
|
||||
return anim.coverTransSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
return arrivalSplitTimes[0];
|
||||
}
|
||||
|
||||
return anim.coverTransSplit[ approachType ][ dir ];
|
||||
}
|
638
animscripts/locked_combat.gsc
Normal file
638
animscripts/locked_combat.gsc
Normal file
@ -0,0 +1,638 @@
|
||||
//****************************************************************************
|
||||
// **
|
||||
// Confidential - (C) Activision Publishing, Inc. 2011 **
|
||||
// **
|
||||
//****************************************************************************
|
||||
// **
|
||||
// Module: Actor locked combat system **
|
||||
// Created: 7/13/11 - John Webb **
|
||||
// **
|
||||
//****************************************************************************
|
||||
|
||||
#include common_scripts\utility;
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\utility;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_combat()
|
||||
{
|
||||
self notify( "killanimscript" );
|
||||
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
self endon( "locked_combat_transition" );
|
||||
animscripts\utility::initialize( "locked_combat" );
|
||||
self.noRunNGun = true;
|
||||
self.dontMelee = true;
|
||||
self.disableExits = true;
|
||||
self.disableArrivals = true;
|
||||
self.disableBulletWhizbyReaction = true;
|
||||
self.keepClaimedNode = false;
|
||||
self.combatMode = "no_cover";
|
||||
|
||||
self animmode( "point_relative" );
|
||||
|
||||
// Setup the locked covernode
|
||||
self locked_setup_covernode( level._locked_combat.nodes[ self.current_node_key ] );
|
||||
|
||||
// Run the cover behavior
|
||||
while ( 1 )
|
||||
{
|
||||
self [[ level._locked_combat.coverTypes[ self.coverType ].behavior_func ]]();
|
||||
wait 0.05;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
locked_setup_covernode( node )
|
||||
{
|
||||
self.coverNode = node;
|
||||
self.coverType = self.coverNode.type;
|
||||
self.a.coverMode = "hide";
|
||||
self.a.atConcealmentNode = false;
|
||||
self.locked_combat = true;
|
||||
self.fixed_node = true; // Need to use something else
|
||||
self.a.pose = "stand";
|
||||
self.fixedNode = false;
|
||||
|
||||
AssertEx( isdefined( level._locked_combat.coverTypes[ self.coverType ] ), "Locked Combat Cover Type " + self.coverType + " has not been initialized." );
|
||||
|
||||
self.hideYawOffset = 0;
|
||||
self.a.leanAim = undefined;
|
||||
self [[ level._locked_combat.coverTypes[ self.coverType ].init_func ]]();
|
||||
|
||||
locked_combat_orient( self.hideYawOffset );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_combat_orient( nodeAngleOffset )
|
||||
{
|
||||
node = self.coverNode;
|
||||
self orientmode( "face angle", self.angles[1] );
|
||||
//self animmode( "point_relative" );
|
||||
|
||||
relYaw = AngleClamp180( self.angles[1] - ( node.angles[1] + nodeAngleOffset ) );
|
||||
|
||||
self thread maintain_orientation();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
maintain_orientation()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
while ( 1 )
|
||||
{
|
||||
self OrientMode( "face angle", self.coverNode.angles[ 1 ] );
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
get_valid_peekouts()
|
||||
{
|
||||
modes = [];
|
||||
modes[ modes.size ] = "stand";
|
||||
modes[ modes.size ] = "crouch";
|
||||
return modes;
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_popUpAndShoot()
|
||||
{
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
locked_combat_orient( self.hideYawOffset );
|
||||
|
||||
if ( !locked_pop_up() )
|
||||
return false;
|
||||
|
||||
locked_shoot();
|
||||
|
||||
self endFireAndAnimIdleThread();
|
||||
|
||||
locked_go_to_hide();
|
||||
|
||||
self.coverCrouchLean_aimmode = undefined;
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_shoot()
|
||||
{
|
||||
self endon( "return_to_cover" );
|
||||
|
||||
self maps\_gameskill::didSomethingOtherThanShooting();
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( isdefined( self.shouldReturnToCover ) )
|
||||
break;
|
||||
|
||||
if ( !isdefined( self.shootPos ) )
|
||||
{
|
||||
assert( !isdefined( self.shootEnt ) );
|
||||
// give shoot_behavior a chance to iterate
|
||||
self waittill( "do_slow_things" );
|
||||
waittillframeend;
|
||||
if ( isdefined( self.shootPos ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !self.bulletsInClip )
|
||||
break;
|
||||
|
||||
self thread aimIdleThread();
|
||||
//println( "Shooting" );
|
||||
shootUntilShootBehaviorChange();
|
||||
|
||||
self clearAnim( %add_fire, .2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_go_to_hide()
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
|
||||
self.changingCoverPos = true;
|
||||
self notify( "done_changing_cover_pos" );
|
||||
|
||||
self endAimIdleThread();
|
||||
|
||||
animRate = 1.0;
|
||||
//animRate = pop_up_and_hide_speed();
|
||||
animation = animArray( self.a.coverMode + "_2_hide" );
|
||||
|
||||
self clearAnim( %body, 0.2 );
|
||||
if ( isdefined( self.current_node_key ) )
|
||||
{
|
||||
node = level._locked_combat.nodes[ self.current_node_key ];
|
||||
assert( isdefined( node ) );
|
||||
self animrelative( "go_to_hide", self.origin, self.angles, animation );
|
||||
}
|
||||
|
||||
//println( "Returning to hide" );
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "go_to_hide" );
|
||||
|
||||
self StopAnimScripted();
|
||||
|
||||
self.a.coverMode = "hide";
|
||||
self animmode( "point_relative" );
|
||||
|
||||
if ( self.coverType == "stand" )
|
||||
self.a.special = "cover_stand";
|
||||
else
|
||||
self.a.special = "cover_crouch";
|
||||
|
||||
self.changingCoverPos = false;
|
||||
}
|
||||
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_pop_up()
|
||||
{
|
||||
assert( !isdefined( self.a.coverMode ) || self.a.coverMode == "hide" );
|
||||
|
||||
newCoverMode = self [[ level._locked_combat.coverTypes[ self.coverType ].cover_mode_func ]]();
|
||||
|
||||
if ( !isdefined( newCoverMode ) )
|
||||
{
|
||||
//println( "No valid coverMode found" );
|
||||
return false;
|
||||
}
|
||||
//println( "Entering coverMode " + newCoverMode );
|
||||
|
||||
timeleft = .1;
|
||||
|
||||
popupAnim = animArray( "hide_2_" + newCoverMode );
|
||||
|
||||
//if ( !self mayMoveToPoint( getAnimEndPos( popupAnim ) ) )
|
||||
//return false;
|
||||
|
||||
if ( self.script == "cover_crouch" && newCoverMode == "lean" )
|
||||
self.coverCrouchLean_aimmode = true;
|
||||
|
||||
self.a.special = "none";
|
||||
self.specialDeathFunc = undefined;
|
||||
|
||||
if ( self.coverType == "stand" )
|
||||
self.a.special = "cover_stand_aim";
|
||||
else if ( self.coverType == "crouch" )
|
||||
self.a.special = "cover_crouch_aim";
|
||||
|
||||
self.changingCoverPos = true;
|
||||
self notify( "done_changing_cover_pos" );
|
||||
|
||||
self animmode( "point_relative" );
|
||||
|
||||
animRate = animscripts\cover_wall::pop_up_and_hide_speed();
|
||||
|
||||
node = level._locked_combat.nodes[ self.current_node_key ];
|
||||
assert( isdefined( node ) );
|
||||
offset_angles = node.angles + ( 0, self.hideYawOffset, 0 );
|
||||
|
||||
self animrelative( "pop_up", node.origin, offset_angles, popUpAnim );
|
||||
|
||||
self thread animscripts\cover_wall::DoNoteTracksForPopup( "pop_up" );
|
||||
|
||||
if ( animHasNoteTrack( popupAnim, "start_aim" ) )
|
||||
{
|
||||
// Store our final step out angle so that we may use it when doing track loop aiming
|
||||
self.stepOutYaw = self.angles[1] + getAngleDelta( popupAnim, 0, 1 );
|
||||
|
||||
self waittillmatch( "pop_up", "start_aim" );
|
||||
timeleft = getAnimLength( popupAnim ) / animRate * ( 1 - self getAnimTime( popupAnim ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
self waittillmatch( "pop_up", "end" );
|
||||
timeleft = .1;
|
||||
}
|
||||
|
||||
//self clearAnim( %cover, timeleft + 0.05 );
|
||||
|
||||
self.a.coverMode = newCoverMode;
|
||||
self.a.prevAttack = newCoverMode;
|
||||
|
||||
self locked_setup_additive_aim( timeleft );
|
||||
self thread animscripts\shared::trackShootEntOrPos();
|
||||
|
||||
wait( timeleft );
|
||||
|
||||
self StopAnimScripted();
|
||||
|
||||
//self clearAnim( popupAnim, 0.1 );
|
||||
|
||||
if ( self isSniper() )
|
||||
{
|
||||
thread animscripts\shoot_behavior::sniper_glint_behavior();
|
||||
}
|
||||
|
||||
self.changingCoverPos = false;
|
||||
self.coverPosEstablishedTime = gettime();
|
||||
|
||||
self notify( "stop_popup_donotetracks" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_setup_additive_aim( transTime )
|
||||
{
|
||||
if ( self.a.coverMode == "left" || self.a.coverMode == "right" )
|
||||
aimCoverMode = "crouch";
|
||||
else
|
||||
aimCoverMode = self.a.coverMode;
|
||||
|
||||
self setAnimKnobAll( animArray( aimCoverMode + "_aim" ), %body, 1, transTime );
|
||||
self setanimlimited( animArray( aimCoverMode + "_aim2" ), 1, 0 );
|
||||
self setanimlimited( animArray( aimCoverMode + "_aim4" ), 1, 0 );
|
||||
self setanimlimited( animArray( aimCoverMode + "_aim6" ), 1, 0 );
|
||||
self setanimlimited( animArray( aimCoverMode + "_aim8" ), 1, 0 );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_aim_idle()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "end_aim_idle_thread" );
|
||||
|
||||
mode = self.a.coverMode;
|
||||
|
||||
if ( isdefined( self.a.aimIdleThread ) )
|
||||
return;
|
||||
self.a.aimIdleThread = true;
|
||||
|
||||
// wait a bit before starting idle since firing will end the idle thread
|
||||
wait 0.1;
|
||||
|
||||
// this used to be setAnim, but it caused problems with turning on its parent nodes when they were supposed to be off (like during pistol pullout).
|
||||
self setAnimLimited( %add_idle, 1, .2 );
|
||||
|
||||
for ( i = 0; ; i++ )
|
||||
{
|
||||
flagname = "idle" + i;
|
||||
idleanim = animArrayPickRandom( mode + "_idle" );
|
||||
self setFlaggedAnimKnobLimitedRestart( flagname, idleanim, 1, 0.2 );
|
||||
self waittillmatch( flagname, "end" );
|
||||
}
|
||||
|
||||
self clearAnim( %add_idle, .1 );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_corner_think( direction, nodeAngleOffset )
|
||||
{
|
||||
self.animArrayFuncs[ "exposed" ][ "stand" ] = animscripts\corner::set_standing_animarray_aiming;
|
||||
self.animArrayFuncs[ "exposed" ][ "crouch" ] = animscripts\corner::set_crouching_animarray_aiming;
|
||||
|
||||
if ( IsDefined( self.customAnimFunc ) && IsDefined( self.customAnimFunc[ "corner_exposed" ] ) )
|
||||
{
|
||||
if ( IsDefined( self.customAnimFunc[ "corner_exposed" ][ "stand" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "exposed" ][ "stand" ] = self.customAnimFunc[ "corner_exposed" ][ "stand" ];
|
||||
}
|
||||
|
||||
if ( IsDefined( self.customAnimFunc[ "corner_exposed" ][ "crouch" ] ) )
|
||||
{
|
||||
self.animArrayFuncs[ "exposed" ][ "crouch" ] = self.customAnimFunc[ "corner_exposed" ][ "crouch" ];
|
||||
}
|
||||
}
|
||||
|
||||
self.cornerDirection = direction;
|
||||
self.a.cornerMode = "unknown";
|
||||
|
||||
self.a.aimIdleThread = undefined;
|
||||
|
||||
animscripts\cover_behavior::turnToMatchNodeDirection( nodeAngleOffset );
|
||||
|
||||
animscripts\corner::set_corner_anim_array();
|
||||
|
||||
self.isshooting = false;
|
||||
self.tracking = false;
|
||||
|
||||
self.cornerAiming = false;
|
||||
|
||||
animscripts\shared::setAnimAimWeight( 0 );
|
||||
|
||||
self.haveGoneToCover = false;
|
||||
|
||||
behaviorCallbacks = spawnstruct();
|
||||
|
||||
if ( !self.fixedNode )
|
||||
behaviorCallbacks.moveToNearByCover = animscripts\cover_behavior::moveToNearbyCover;
|
||||
|
||||
behaviorCallbacks.mainLoopStart = ::locked_corner_mainLoopStart;
|
||||
behaviorCallbacks.reload = animscripts\corner::cornerReload;
|
||||
behaviorCallbacks.leaveCoverAndShoot = animscripts\corner::stepOutAndShootEnemy;
|
||||
behaviorCallbacks.look = animscripts\corner::lookForEnemy;
|
||||
behaviorCallbacks.fastlook = animscripts\corner::fastlook;
|
||||
behaviorCallbacks.idle = animscripts\corner::idle;
|
||||
behaviorCallbacks.grenade = ::return_false;
|
||||
behaviorCallbacks.grenadehidden = ::return_false;
|
||||
behaviorCallbacks.blindfire = animscripts\corner::blindfire;
|
||||
|
||||
animscripts\cover_behavior::main( behaviorCallbacks );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_corner_mainLoopStart()
|
||||
{
|
||||
desiredStance = "stand";
|
||||
|
||||
/#
|
||||
if ( getdvarint( "scr_cornerforcecrouch" ) == 1 )
|
||||
desiredStance = "crouch";
|
||||
#/
|
||||
|
||||
self animscripts\corner::transitionToStance( desiredStance );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_moveToNearbyCover()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_reload()
|
||||
{
|
||||
return Reload( 2.0, animArray( "reload" ) );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_look( lookTime )
|
||||
{
|
||||
if ( !isdefined( self.a.array[ "hide_to_look" ] ) )
|
||||
return false;
|
||||
|
||||
if ( !locked_peekOut() )
|
||||
return false;
|
||||
|
||||
animscripts\shared::playLookAnimation( animArray( "look_idle" ), lookTime );// TODO: replace
|
||||
|
||||
lookanim = undefined;
|
||||
if ( self isSuppressedWrapper() )
|
||||
lookanim = animArray( "look_to_hide_fast" );
|
||||
else
|
||||
lookanim = animArray( "look_to_hide" );
|
||||
|
||||
self setflaggedanimknoballrestart( "looking_end", lookanim, %body, 1, .1 );
|
||||
animscripts\shared::DoNoteTracks( "looking_end" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_peekOut()
|
||||
{
|
||||
if ( isdefined( self.coverNode.script_dontpeek ) )
|
||||
return false;
|
||||
|
||||
// assuming no delta, so no maymovetopoint check
|
||||
|
||||
self setFlaggedAnimKnobAll( "looking_start", animArray( "hide_to_look" ), %body, 1, .2 );
|
||||
animscripts\shared::DoNoteTracks( "looking_start" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_fastlook()
|
||||
{
|
||||
self setFlaggedAnimKnobAllRestart( "look", animArrayPickRandom( "look" ), %body, 1, .1 );
|
||||
self animscripts\shared::DoNoteTracks( "look" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_idle()
|
||||
{
|
||||
self endon( "end_idle" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
useTwitch = ( randomint( 2 ) == 0 && animArrayAnyExist( "hide_idle_twitch" ) );
|
||||
if ( useTwitch )
|
||||
idleanim = animArrayPickRandom( "hide_idle_twitch" );
|
||||
else
|
||||
idleanim = animarray( "hide_idle" );
|
||||
|
||||
locked_playIdleAnimation( idleAnim, useTwitch );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_playIdleAnimation( idleAnim, needsRestart )
|
||||
{
|
||||
if ( needsRestart )
|
||||
self setFlaggedAnimKnobAllRestart( "idle", idleAnim, %body, 1, 0.25, 1 );
|
||||
else
|
||||
self setFlaggedAnimKnobAll( "idle", idleAnim, %body, 1, 0.25, 1 );
|
||||
|
||||
self.a.coverMode = "hide";
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "idle" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_flinch()
|
||||
{
|
||||
if ( !animArrayAnyExist( "hide_idle_flinch" ) )
|
||||
return false;
|
||||
|
||||
forward = anglesToForward( self.angles );
|
||||
stepto = self.origin + vector_multiply( forward, -16 );
|
||||
|
||||
if ( !self mayMoveToPoint( stepto ) )
|
||||
return false;
|
||||
|
||||
self animmode( "point_relative" );
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
flinchanim = animArrayPickRandom( "hide_idle_flinch" );
|
||||
locked_playIdleAnimation( flinchanim, true );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_blindfire()
|
||||
{
|
||||
if ( !animArrayAnyExist( "blind_fire" ) )
|
||||
return false;
|
||||
|
||||
self animMode( "point_relative" );
|
||||
self.keepClaimedNodeIfValid = true;
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "blindfire", animArrayPickRandom( "blind_fire" ), %body, 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "blindfire" );
|
||||
|
||||
self.keepClaimedNodeIfValid = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
return_false( param1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
locked_grenade( throwAt, safe )
|
||||
{
|
||||
if ( !isPlayer( throwAt ) ) // Only throw grenades at players for now
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isdefined( self.dontEverShoot ) || isdefined( throwAt.dontAttackMe ) )
|
||||
return false;
|
||||
|
||||
// We want to only throw locked_combat grenades if the player is trying to hide
|
||||
if ( !(throwAt should_grenade_player()) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
theanim = undefined;
|
||||
if ( isdefined( safe ) && safe )
|
||||
theanim = animArrayPickRandom( "grenade_safe" );
|
||||
else
|
||||
theanim = animArrayPickRandom( "grenade_exposed" );
|
||||
|
||||
threwGrenade = TryGrenade( throwAt, theanim );
|
||||
|
||||
return threwGrenade;
|
||||
}
|
||||
|
||||
should_grenade_player()
|
||||
{
|
||||
assert( isPlayer( self ) );
|
||||
assert( isDefined( self.locked_shouldGrenade ) );
|
||||
return self.locked_shouldGrenade;
|
||||
}
|
1627
animscripts/lunar/animset.gsc
Normal file
1627
animscripts/lunar/animset.gsc
Normal file
File diff suppressed because it is too large
Load Diff
35
animscripts/lunar/init.gsc
Normal file
35
animscripts/lunar/init.gsc
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
#include animscripts\init_common;
|
||||
|
||||
main()
|
||||
{
|
||||
prof_begin( "animscript_init" );
|
||||
|
||||
pre_first_init();
|
||||
firstInit();
|
||||
post_first_init();
|
||||
|
||||
prof_end( "animscript_init" );
|
||||
}
|
||||
|
||||
firstInit()
|
||||
{
|
||||
// Initialization that should happen once per level
|
||||
if ( isDefined( anim.NotFirstTime ) )// Use this to trigger the first init
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pre_anim_init();
|
||||
|
||||
animscripts\lunar\animset::init_anim_sets();//lunar version
|
||||
animscripts\lunar\init_move_transitions::initMoveStartStopTransitions();
|
||||
|
||||
anim.lastGibTime = 0;
|
||||
anim.gibDelay = 3 * 1000; // 3 seconds
|
||||
anim.minGibs = 2;
|
||||
anim.maxGibs = 4;
|
||||
anim.totalGibs = RandomIntRange( anim.minGibs, anim.maxGibs );
|
||||
|
||||
post_anim_init();
|
||||
}
|
982
animscripts/lunar/init_move_transitions.gsc
Normal file
982
animscripts/lunar/init_move_transitions.gsc
Normal file
@ -0,0 +1,982 @@
|
||||
#include animscripts\Utility;
|
||||
#include maps\_utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
//The LUNAR version.
|
||||
|
||||
init_move_transition_arrays()
|
||||
{
|
||||
if ( isdefined( anim.move_transition_arrays ) )
|
||||
return;
|
||||
|
||||
anim.move_transition_arrays = 1;
|
||||
|
||||
anim.coverTrans = [];
|
||||
anim.coverExit = [];
|
||||
anim.maxDirections = [];
|
||||
anim.excludeDir = [];
|
||||
|
||||
anim.traverseInfo = [];
|
||||
|
||||
anim.coverTransLongestDist = [];
|
||||
anim.coverTransDist = [];
|
||||
anim.coverExitDist = [];
|
||||
|
||||
// this is the distance moved to get around corner for 7, 8, 9 directions
|
||||
anim.coverExitPostDist = [];
|
||||
|
||||
// this is the distance moved to get around corner for 7, 8, 9 directions
|
||||
anim.coverTransPreDist = [];
|
||||
|
||||
anim.coverTransAngles = [];
|
||||
anim.coverExitAngles = [];
|
||||
|
||||
anim.coverExitSplit = [];
|
||||
anim.coverTransSplit = [];
|
||||
|
||||
anim.arrivalEndStance = [];
|
||||
}
|
||||
|
||||
|
||||
initMoveStartStopTransitions()
|
||||
{
|
||||
init_move_transition_arrays();
|
||||
|
||||
// Move transition points
|
||||
init_moon_transition_points();
|
||||
|
||||
// TEMP, remove this flag
|
||||
level._newArrivals = true;
|
||||
|
||||
transTypes = [];
|
||||
transTypes[ 0 ] = "left";
|
||||
transTypes[ 1 ] = "right";
|
||||
transTypes[ 2 ] = "left_crouch";
|
||||
transTypes[ 3 ] = "right_crouch";
|
||||
transTypes[ 4 ] = "crouch";
|
||||
transTypes[ 5 ] = "stand";
|
||||
transTypes[ 6 ] = "exposed";
|
||||
transTypes[ 7 ] = "exposed_crouch";
|
||||
transTypes[ 8 ] = "stand_saw";
|
||||
transTypes[ 9 ] = "prone_saw";
|
||||
transTypes[ 10 ] = "crouch_saw";
|
||||
transTypes[ 11 ] = "wall_over_40";
|
||||
transTypes[ 12 ] = "right_cqb";
|
||||
transTypes[ 13 ] = "right_crouch_cqb";
|
||||
transTypes[ 14 ] = "left_cqb";
|
||||
transTypes[ 15 ] = "left_crouch_cqb";
|
||||
transTypes[ 16 ] = "exposed_cqb";
|
||||
transTypes[ 17 ] = "exposed_crouch_cqb";
|
||||
transTypes[ 18 ] = "heat";
|
||||
transTypes[ 19 ] = "heat_left";
|
||||
transTypes[ 20 ] = "heat_right";
|
||||
|
||||
|
||||
lastCoverTrans = 6;
|
||||
|
||||
// tagJW<NOTE>: Non-lunar movements do not use move transition notes
|
||||
// Moon_actor's main is called before load, so don't override these if they exist
|
||||
if ( !isdefined( anim.run_transition_notes ) )
|
||||
{
|
||||
anim.cqb_transition_notes = [];
|
||||
anim.cqb_transition_points = [];
|
||||
|
||||
anim.run_transition_notes = [];
|
||||
anim.run_transition_points = [];
|
||||
}
|
||||
|
||||
anim.approach_types = [];
|
||||
|
||||
anim.approach_types[ "Cover Left" ] = [];
|
||||
anim.approach_types[ "Cover Left" ][ "stand" ] = "left";
|
||||
anim.approach_types[ "Cover Left" ][ "crouch" ] = "left_crouch";
|
||||
anim.maxDirections[ "Cover Left" ] = 9;
|
||||
anim.excludeDir[ "Cover Left" ] = 9;
|
||||
|
||||
anim.approach_types[ "Cover Right" ] = [];
|
||||
anim.approach_types[ "Cover Right" ][ "stand" ] = "right";
|
||||
anim.approach_types[ "Cover Right" ][ "crouch" ] = "right_crouch";
|
||||
anim.maxDirections[ "Cover Right" ] = 9;
|
||||
anim.excludeDir[ "Cover Right" ] = 7;
|
||||
|
||||
anim.approach_types[ "Cover Crouch" ] = [];
|
||||
anim.approach_types[ "Cover Crouch" ][ "stand" ] = "crouch";
|
||||
anim.approach_types[ "Cover Crouch" ][ "crouch" ] = "crouch";
|
||||
anim.approach_types[ "Conceal Crouch" ] = anim.approach_types[ "Cover Crouch" ];
|
||||
anim.approach_types[ "Cover Crouch Window" ] = anim.approach_types[ "Cover Crouch" ];
|
||||
anim.maxDirections[ "Cover Crouch" ] = 6;
|
||||
anim.excludeDir[ "Cover Crouch" ] = -1;
|
||||
anim.maxDirections[ "Conceal Crouch" ] = 6;
|
||||
anim.excludeDir[ "Conceal Crouch" ] = -1;
|
||||
|
||||
anim.approach_types[ "Cover Stand" ] = [];
|
||||
anim.approach_types[ "Cover Stand" ][ "stand" ] = "stand";
|
||||
anim.approach_types[ "Cover Stand" ][ "crouch" ] = "stand";
|
||||
anim.approach_types[ "Conceal Stand" ] = anim.approach_types[ "Cover Stand" ];
|
||||
anim.maxDirections[ "Cover Stand" ] = 6;
|
||||
anim.excludeDir[ "Cover Stand" ] = -1;
|
||||
anim.maxDirections[ "Conceal Stand" ] = 6;
|
||||
anim.excludeDir[ "Conceal Stand" ] = -1;
|
||||
|
||||
anim.approach_types[ "Cover Prone" ] = [];
|
||||
anim.approach_types[ "Cover Prone" ][ "stand" ] = "exposed";
|
||||
anim.approach_types[ "Cover Prone" ][ "crouch" ] = "exposed";
|
||||
anim.approach_types[ "Conceal Prone" ] = anim.approach_types[ "Cover Prone" ];
|
||||
anim.excludeDir[ "Conceal Prone" ] = -1;
|
||||
|
||||
anim.approach_types[ "Path" ] = [];
|
||||
anim.approach_types[ "Path" ][ "stand" ] = "exposed";
|
||||
anim.approach_types[ "Path" ][ "crouch" ] = "exposed_crouch";
|
||||
anim.approach_types[ "Guard" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Ambush" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Scripted" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Custom" ] = anim.approach_types[ "Path" ];
|
||||
anim.approach_types[ "Exposed" ] = anim.approach_types[ "Path" ];
|
||||
|
||||
anim.isCombatPathNode[ "Guard" ] = true;
|
||||
anim.isCombatPathNode[ "Ambush" ] = true;
|
||||
anim.isCombatPathNode[ "Exposed" ] = true;
|
||||
|
||||
// used by level script to orient AI in certain ways at a node
|
||||
anim.isCombatScriptNode[ "Guard" ] = true;
|
||||
anim.isCombatScriptNode[ "Exposed" ] = true;
|
||||
|
||||
// CORNER TRANSITIONS ANIMS
|
||||
// indicies indicate the keyboard numpad directions (8 is forward)
|
||||
// 7 8 9
|
||||
// 4 6 <- 5 is invalid
|
||||
// 1 2 3
|
||||
|
||||
/*************************************************
|
||||
* Entrance Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverTrans[ "right" ][ 1 ] = %tp_moon_coverR_run_2_stand_BL;
|
||||
anim.coverTrans[ "right" ][ 2 ] = %tp_moon_coverR_run_2_stand_B;
|
||||
anim.coverTrans[ "right" ][ 3 ] = %tp_moon_coverR_run_2_stand_BR;
|
||||
anim.coverTrans[ "right" ][ 4 ] = %tp_moon_coverR_run_2_stand_L;
|
||||
anim.coverTrans[ "right" ][ 6 ] = %tp_moon_coverR_run_2_stand_R;
|
||||
//im.coverTrans[ "right" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right" ][ 8 ] = %tp_moon_coverR_run_2_stand_F;
|
||||
anim.coverTrans[ "right" ][ 9 ] = %tp_moon_coverR_run_2_stand_FR;
|
||||
|
||||
anim.coverTrans[ "right_crouch" ][ 1 ] = %tp_moon_coverR_run_2_crouch_BL;
|
||||
anim.coverTrans[ "right_crouch" ][ 2 ] = %tp_moon_coverR_run_2_crouch_B;
|
||||
anim.coverTrans[ "right_crouch" ][ 3 ] = %tp_moon_coverR_run_2_crouch_BR;
|
||||
anim.coverTrans[ "right_crouch" ][ 4 ] = %tp_moon_coverR_run_2_crouch_L;
|
||||
anim.coverTrans[ "right_crouch" ][ 6 ] = %tp_moon_coverR_run_2_crouch_R;
|
||||
//im.coverTrans[ "right_crouch" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_crouch" ][ 8 ] = %tp_moon_coverR_run_2_crouch_F;
|
||||
anim.coverTrans[ "right_crouch" ][ 9 ] = %tp_moon_coverR_run_2_crouch_FR;
|
||||
|
||||
anim.coverTrans[ "right_cqb" ][ 1 ] = %tp_moon_coverR_run_2_stand_BL;
|
||||
anim.coverTrans[ "right_cqb" ][ 2 ] = %tp_moon_coverR_run_2_stand_B;
|
||||
anim.coverTrans[ "right_cqb" ][ 3 ] = %tp_moon_coverR_run_2_stand_BR;
|
||||
anim.coverTrans[ "right_cqb" ][ 4 ] = %tp_moon_coverR_run_2_stand_L;
|
||||
anim.coverTrans[ "right_cqb" ][ 6 ] = %tp_moon_coverR_run_2_stand_R;
|
||||
//im.coverTrans[ "right_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_cqb" ][ 8 ] = %tp_moon_coverR_run_2_stand_F;
|
||||
anim.coverTrans[ "right_cqb" ][ 9 ] = %tp_moon_coverR_run_2_stand_FR;
|
||||
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 1 ] = %tp_moon_cqb_coverR_run_2_crouch_BL;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 2 ] = %tp_moon_cqb_coverR_run_2_crouch_B;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 3 ] = %tp_moon_cqb_coverR_run_2_crouch_BR;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 4 ] = %tp_moon_cqb_coverR_run_2_crouch_L;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 6 ] = %tp_moon_cqb_coverR_run_2_crouch_R;
|
||||
//im.coverTrans[ "right_crouch_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 8 ] = %tp_moon_cqb_coverR_run_2_crouch_F;
|
||||
anim.coverTrans[ "right_crouch_cqb" ][ 9 ] = %tp_moon_cqb_coverR_run_2_crouch_FR;
|
||||
|
||||
anim.coverTrans[ "left" ][ 1 ] = %tp_moon_coverL_run_2_stand_BL;
|
||||
anim.coverTrans[ "left" ][ 2 ] = %tp_moon_coverL_run_2_stand_B;
|
||||
anim.coverTrans[ "left" ][ 3 ] = %tp_moon_coverL_run_2_stand_BR;
|
||||
anim.coverTrans[ "left" ][ 4 ] = %tp_moon_coverL_run_2_stand_L;
|
||||
anim.coverTrans[ "left" ][ 6 ] = %tp_moon_coverL_run_2_stand_R;
|
||||
anim.coverTrans[ "left" ][ 7 ] = %tp_moon_coverL_run_2_stand_FL;
|
||||
anim.coverTrans[ "left" ][ 8 ] = %tp_moon_coverL_run_2_stand_F;
|
||||
//im.coverTrans[ "left" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_crouch" ][ 1 ] = %tp_moon_coverL_run_2_crouch_BL;
|
||||
anim.coverTrans[ "left_crouch" ][ 2 ] = %tp_moon_coverL_run_2_crouch_B;
|
||||
anim.coverTrans[ "left_crouch" ][ 3 ] = %tp_moon_coverL_run_2_crouch_BR;
|
||||
anim.coverTrans[ "left_crouch" ][ 4 ] = %tp_moon_coverL_run_2_crouch_L;
|
||||
anim.coverTrans[ "left_crouch" ][ 6 ] = %tp_moon_coverL_run_2_crouch_R;
|
||||
anim.coverTrans[ "left_crouch" ][ 7 ] = %tp_moon_coverL_run_2_crouch_FL;
|
||||
anim.coverTrans[ "left_crouch" ][ 8 ] = %tp_moon_coverL_run_2_crouch_F;
|
||||
//im.coverTrans[ "left_crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_cqb" ][ 1 ] = %tp_moon_coverL_run_2_stand_BL;
|
||||
anim.coverTrans[ "left_cqb" ][ 2 ] = %tp_moon_coverL_run_2_stand_B;
|
||||
anim.coverTrans[ "left_cqb" ][ 3 ] = %tp_moon_coverL_run_2_stand_BR;
|
||||
anim.coverTrans[ "left_cqb" ][ 4 ] = %tp_moon_coverL_run_2_stand_L;
|
||||
anim.coverTrans[ "left_cqb" ][ 6 ] = %tp_moon_coverL_run_2_stand_R;
|
||||
anim.coverTrans[ "left_cqb" ][ 7 ] = %tp_moon_coverL_run_2_stand_FL;
|
||||
anim.coverTrans[ "left_cqb" ][ 8 ] = %tp_moon_coverL_run_2_stand_F;
|
||||
//im.coverTrans[ "left_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 1 ] = %tp_moon_cqb_coverL_run_2_crouch_BL;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 2 ] = %tp_moon_cqb_coverL_run_2_crouch_B;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 3 ] = %tp_moon_cqb_coverL_run_2_crouch_BR;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 4 ] = %tp_moon_cqb_coverL_run_2_crouch_L;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 6 ] = %tp_moon_cqb_coverL_run_2_crouch_R;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 7 ] = %tp_moon_cqb_coverL_run_2_crouch_FL;
|
||||
anim.coverTrans[ "left_crouch_cqb" ][ 8 ] = %tp_moon_cqb_coverL_run_2_crouch_F;
|
||||
//im.coverTrans[ "left_crouch_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "crouch" ][ 1 ] = %tp_moon_coverF_run_2_crouch_BL;
|
||||
anim.coverTrans[ "crouch" ][ 2 ] = %tp_moon_coverF_run_2_crouch_B;
|
||||
anim.coverTrans[ "crouch" ][ 3 ] = %tp_moon_coverF_run_2_crouch_BR;
|
||||
anim.coverTrans[ "crouch" ][ 4 ] = %tp_moon_coverF_run_2_crouch_L;
|
||||
anim.coverTrans[ "crouch" ][ 6 ] = %tp_moon_coverF_run_2_crouch_R;
|
||||
//im.coverTrans[ "crouch" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "crouch" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "stand" ][ 1 ] = %tp_moon_coverF_run_2_stand_BL;
|
||||
anim.coverTrans[ "stand" ][ 2 ] = %tp_moon_coverF_run_2_stand_B;
|
||||
anim.coverTrans[ "stand" ][ 3 ] = %tp_moon_coverF_run_2_stand_BR;
|
||||
anim.coverTrans[ "stand" ][ 4 ] = %tp_moon_coverF_run_2_stand_L;
|
||||
anim.coverTrans[ "stand" ][ 6 ] = %tp_moon_coverF_run_2_stand_R;
|
||||
//im.coverTrans[ "stand" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "stand" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverTrans[ "stand" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverTrans[ "stand_saw" ][ 1 ] = %saw_gunner_runin_ML;
|
||||
anim.coverTrans[ "stand_saw" ][ 2 ] = %saw_gunner_runin_M;
|
||||
anim.coverTrans[ "stand_saw" ][ 3 ] = %saw_gunner_runin_MR;
|
||||
anim.coverTrans[ "stand_saw" ][ 4 ] = %saw_gunner_runin_L;
|
||||
anim.coverTrans[ "stand_saw" ][ 6 ] = %saw_gunner_runin_R;
|
||||
|
||||
anim.coverTrans[ "crouch_saw" ][ 1 ] = %saw_gunner_lowwall_runin_ML;
|
||||
anim.coverTrans[ "crouch_saw" ][ 2 ] = %saw_gunner_lowwall_runin_M;
|
||||
anim.coverTrans[ "crouch_saw" ][ 3 ] = %saw_gunner_lowwall_runin_MR;
|
||||
anim.coverTrans[ "crouch_saw" ][ 4 ] = %saw_gunner_lowwall_runin_L;
|
||||
anim.coverTrans[ "crouch_saw" ][ 6 ] = %saw_gunner_lowwall_runin_R;
|
||||
|
||||
anim.coverTrans[ "prone_saw" ][ 1 ] = %saw_gunner_prone_runin_ML;
|
||||
anim.coverTrans[ "prone_saw" ][ 2 ] = %saw_gunner_prone_runin_M;
|
||||
anim.coverTrans[ "prone_saw" ][ 3 ] = %saw_gunner_prone_runin_MR;
|
||||
|
||||
// we need 45 degree angle approaches for exposed...
|
||||
anim.coverTrans[ "exposed" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed" ][ 1 ] = %tp_moon_exposed_run_2_stand_BL;
|
||||
anim.coverTrans[ "exposed" ][ 2 ] = %tp_moon_exposed_run_2_stand_B;
|
||||
anim.coverTrans[ "exposed" ][ 3 ] = %tp_moon_exposed_run_2_stand_BR;
|
||||
anim.coverTrans[ "exposed" ][ 4 ] = %tp_moon_exposed_run_2_stand_L;
|
||||
anim.coverTrans[ "exposed" ][ 6 ] = %tp_moon_exposed_run_2_stand_R;
|
||||
anim.coverTrans[ "exposed" ][ 7 ] = %tp_moon_exposed_run_2_stand_FL;
|
||||
anim.coverTrans[ "exposed" ][ 8 ] = %tp_moon_exposed_run_2_stand_F;
|
||||
anim.coverTrans[ "exposed" ][ 9 ] = %tp_moon_exposed_run_2_stand_FR;
|
||||
|
||||
anim.coverTrans[ "exposed_crouch" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_crouch" ][ 1 ] = %tp_moon_exposed_run_2_crouch_BL;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 2 ] = %tp_moon_exposed_run_2_crouch_B;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 3 ] = %tp_moon_exposed_run_2_crouch_BR;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 4 ] = %tp_moon_exposed_run_2_crouch_L;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 6 ] = %tp_moon_exposed_run_2_crouch_R;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 7 ] = %tp_moon_exposed_run_2_crouch_FL;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 8 ] = %tp_moon_exposed_run_2_crouch_F;
|
||||
anim.coverTrans[ "exposed_crouch" ][ 9 ] = %tp_moon_exposed_run_2_crouch_FR;
|
||||
|
||||
anim.coverTrans[ "exposed_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_cqb" ][ 1 ] = %tp_moon_cqb_exposed_run_2_stand_BL;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 2 ] = %tp_moon_cqb_exposed_run_2_stand_B;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 3 ] = %tp_moon_cqb_exposed_run_2_stand_BR;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 4 ] = %tp_moon_cqb_exposed_run_2_stand_L;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 6 ] = %tp_moon_cqb_exposed_run_2_stand_R;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 7 ] = %tp_moon_cqb_exposed_run_2_stand_FL;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 8 ] = %tp_moon_cqb_exposed_run_2_stand_F;
|
||||
anim.coverTrans[ "exposed_cqb" ][ 9 ] = %tp_moon_cqb_exposed_run_2_stand_FR;
|
||||
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 1 ] = %tp_moon_exposed_run_2_crouch_BL;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 2 ] = %tp_moon_exposed_run_2_crouch_B;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 3 ] = %tp_moon_exposed_run_2_crouch_BR;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 4 ] = %tp_moon_exposed_run_2_crouch_L;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 6 ] = %tp_moon_exposed_run_2_crouch_R;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 7 ] = %tp_moon_exposed_run_2_crouch_FL;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 8 ] = %tp_moon_exposed_run_2_crouch_F;
|
||||
anim.coverTrans[ "exposed_crouch_cqb" ][ 9 ] = %tp_moon_exposed_run_2_crouch_FR;
|
||||
|
||||
anim.coverTrans[ "heat" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverTrans[ "heat" ][ 1 ] = %heat_approach_1;
|
||||
anim.coverTrans[ "heat" ][ 2 ] = %heat_approach_2;
|
||||
anim.coverTrans[ "heat" ][ 3 ] = %heat_approach_3;
|
||||
anim.coverTrans[ "heat" ][ 4 ] = %heat_approach_4;
|
||||
anim.coverTrans[ "heat" ][ 6 ] = %heat_approach_6;
|
||||
//anim.coverTrans[ "heat" ][ 7 ] = %heat_approach_8;
|
||||
anim.coverTrans[ "heat" ][ 8 ] = %heat_approach_8;
|
||||
//anim.coverTrans[ "heat" ][ 9 ] = %heat_approach_8;
|
||||
|
||||
anim.coverTrans[ "heat_left" ] = [];
|
||||
anim.coverTrans[ "heat_right" ] = [];
|
||||
|
||||
/*************************************************
|
||||
* Step in position Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverStepInAnim = [];
|
||||
anim.coverStepInAnim[ "right" ] = %corner_standR_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "right_crouch" ] = %CornerCrR_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "left" ] = %corner_standL_trans_B_2_alert_v2;
|
||||
anim.coverStepInAnim[ "left_crouch" ] = %CornerCrL_trans_B_2_alert;
|
||||
anim.coverStepInAnim[ "crouch" ] = %covercrouch_aim_2_hide;
|
||||
anim.coverStepInAnim[ "stand" ] = %coverstand_aim_2_hide;
|
||||
|
||||
anim.coverStepInOffsets = [];
|
||||
anim.coverStepInAngles = [];
|
||||
|
||||
for( i = 0; i < lastCoverTrans; i++ )
|
||||
{
|
||||
trans = transTypes[i];
|
||||
anim.coverStepInOffsets[ trans ] = getMoveDelta( anim.coverStepInAnim[ trans ], 0, 1 );
|
||||
anim.coverStepInAngles[ trans ] = getAngleDelta( anim.coverStepInAnim[ trans ], 0, 1 );
|
||||
}
|
||||
|
||||
anim.coverStepInAngles[ "right" ] += 90;
|
||||
anim.coverStepInAngles[ "right_crouch" ] += 90;
|
||||
anim.coverStepInAngles[ "left" ] -= 90;
|
||||
anim.coverStepInAngles[ "left_crouch" ] -= 90;
|
||||
|
||||
/*************************************************
|
||||
* Traverse Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverTrans[ "wall_over_96" ][ 1 ] = %traverse90_IN_ML;
|
||||
anim.coverTrans[ "wall_over_96" ][ 2 ] = %traverse90_IN_M;
|
||||
anim.coverTrans[ "wall_over_96" ][ 3 ] = %traverse90_IN_MR;
|
||||
anim.traverseInfo[ "wall_over_96" ][ "height" ] = 96;
|
||||
|
||||
anim.coverTrans[ "wall_over_40" ][ 1 ] = %traverse_window_M_2_run;
|
||||
anim.coverTrans[ "wall_over_40" ][ 2 ] = %traverse_window_M_2_run;
|
||||
anim.coverTrans[ "wall_over_40" ][ 3 ] = %traverse_window_M_2_run;
|
||||
|
||||
/*
|
||||
anim.coverTrans["wall_over_40"][1] = %traverse40_IN_ML;
|
||||
anim.coverTrans["wall_over_40"][2] = %traverse40_IN_M;
|
||||
anim.coverTrans["wall_over_40"][3] = %traverse40_IN_MR;
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
/*************************************************
|
||||
* Exit Animations
|
||||
*************************************************/
|
||||
|
||||
anim.coverExit[ "right" ][ 1 ] = %tp_moon_coverR_stand_2_run_BL;
|
||||
anim.coverExit[ "right" ][ 2 ] = %tp_moon_coverR_stand_2_run_B;
|
||||
anim.coverExit[ "right" ][ 3 ] = %tp_moon_coverR_stand_2_run_BR;
|
||||
anim.coverExit[ "right" ][ 4 ] = %tp_moon_coverR_stand_2_run_L;
|
||||
anim.coverExit[ "right" ][ 6 ] = %tp_moon_coverR_stand_2_run_R;
|
||||
//im.coverExit[ "right" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right" ][ 8 ] = %tp_moon_coverR_stand_2_run_F;
|
||||
anim.coverExit[ "right" ][ 9 ] = %tp_moon_coverR_stand_2_run_FR;
|
||||
|
||||
anim.coverExit[ "right_crouch" ][ 1 ] = %tp_moon_coverR_crouch_2_run_BL;
|
||||
anim.coverExit[ "right_crouch" ][ 2 ] = %tp_moon_coverR_crouch_2_run_B;
|
||||
anim.coverExit[ "right_crouch" ][ 3 ] = %tp_moon_coverR_crouch_2_run_BR;
|
||||
anim.coverExit[ "right_crouch" ][ 4 ] = %tp_moon_coverR_crouch_2_run_L;
|
||||
anim.coverExit[ "right_crouch" ][ 6 ] = %tp_moon_coverR_crouch_2_run_R;
|
||||
//im.coverExit[ "right_crouch" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_crouch" ][ 8 ] = %tp_moon_coverR_crouch_2_run_F;
|
||||
anim.coverExit[ "right_crouch" ][ 9 ] = %tp_moon_coverR_crouch_2_run_FR;
|
||||
|
||||
anim.coverExit[ "right_cqb" ][ 1 ] = %tp_moon_coverR_stand_2_run_BL;
|
||||
anim.coverExit[ "right_cqb" ][ 2 ] = %tp_moon_coverR_stand_2_run_B;
|
||||
anim.coverExit[ "right_cqb" ][ 3 ] = %tp_moon_coverR_stand_2_run_BR;
|
||||
anim.coverExit[ "right_cqb" ][ 4 ] = %tp_moon_coverR_stand_2_run_L;
|
||||
anim.coverExit[ "right_cqb" ][ 6 ] = %tp_moon_coverR_stand_2_run_R;
|
||||
//im.coverExit[ "right_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_cqb" ][ 8 ] = %tp_moon_coverR_stand_2_run_F;
|
||||
anim.coverExit[ "right_cqb" ][ 9 ] = %tp_moon_coverR_stand_2_run_FR;
|
||||
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 1 ] = %tp_moon_cqb_coverR_crouch_2_run_BL;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 2 ] = %tp_moon_cqb_coverR_crouch_2_run_B;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 3 ] = %tp_moon_cqb_coverR_crouch_2_run_BR;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 4 ] = %tp_moon_cqb_coverR_crouch_2_run_L;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 6 ] = %tp_moon_cqb_coverR_crouch_2_run_R;
|
||||
//im.coverExit[ "right_crouch_cqb" ][ 7 ] = can't approach from this direction;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 8 ] = %tp_moon_cqb_coverR_crouch_2_run_F;
|
||||
anim.coverExit[ "right_crouch_cqb" ][ 9 ] = %tp_moon_cqb_coverR_crouch_2_run_FR;
|
||||
|
||||
|
||||
anim.coverExit[ "left" ][ 1 ] = %tp_moon_coverL_stand_2_run_BL;
|
||||
anim.coverExit[ "left" ][ 2 ] = %tp_moon_coverL_stand_2_run_B;
|
||||
anim.coverExit[ "left" ][ 3 ] = %tp_moon_coverL_stand_2_run_BR;
|
||||
anim.coverExit[ "left" ][ 4 ] = %tp_moon_coverL_stand_2_run_L;
|
||||
anim.coverExit[ "left" ][ 6 ] = %tp_moon_coverL_stand_2_run_R;
|
||||
anim.coverExit[ "left" ][ 7 ] = %tp_moon_coverL_stand_2_run_FL;
|
||||
anim.coverExit[ "left" ][ 8 ] = %tp_moon_coverL_stand_2_run_F;
|
||||
//im.coverExit[ "left" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_crouch" ][ 1 ] = %tp_moon_coverL_crouch_2_run_BL;
|
||||
anim.coverExit[ "left_crouch" ][ 2 ] = %tp_moon_coverL_crouch_2_run_B;
|
||||
anim.coverExit[ "left_crouch" ][ 3 ] = %tp_moon_coverL_crouch_2_run_BR;
|
||||
anim.coverExit[ "left_crouch" ][ 4 ] = %tp_moon_coverL_crouch_2_run_L;
|
||||
anim.coverExit[ "left_crouch" ][ 6 ] = %tp_moon_coverL_crouch_2_run_R;
|
||||
anim.coverExit[ "left_crouch" ][ 7 ] = %tp_moon_coverL_crouch_2_run_FL;
|
||||
anim.coverExit[ "left_crouch" ][ 8 ] = %tp_moon_coverL_crouch_2_run_F;
|
||||
//im.coverExit[ "left_crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_cqb" ][ 1 ] = %tp_moon_coverL_stand_2_run_BL;
|
||||
anim.coverExit[ "left_cqb" ][ 2 ] = %tp_moon_coverL_stand_2_run_B;
|
||||
anim.coverExit[ "left_cqb" ][ 3 ] = %tp_moon_coverL_stand_2_run_BR;
|
||||
anim.coverExit[ "left_cqb" ][ 4 ] = %tp_moon_coverL_stand_2_run_L;
|
||||
anim.coverExit[ "left_cqb" ][ 6 ] = %tp_moon_coverL_stand_2_run_R;
|
||||
anim.coverExit[ "left_cqb" ][ 7 ] = %tp_moon_coverL_stand_2_run_FL;
|
||||
anim.coverExit[ "left_cqb" ][ 8 ] = %tp_moon_coverL_stand_2_run_F;
|
||||
//im.coverExit[ "left_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 1 ] = %tp_moon_cqb_coverL_crouch_2_run_BL;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 2 ] = %tp_moon_cqb_coverL_crouch_2_run_B;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 3 ] = %tp_moon_cqb_coverL_crouch_2_run_BR;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 4 ] = %tp_moon_cqb_coverL_crouch_2_run_L;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 6 ] = %tp_moon_cqb_coverL_crouch_2_run_R;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 7 ] = %tp_moon_cqb_coverL_crouch_2_run_FL;
|
||||
anim.coverExit[ "left_crouch_cqb" ][ 8 ] = %tp_moon_cqb_coverL_crouch_2_run_F;
|
||||
//im.coverExit[ "left_crouch_cqb" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "crouch" ][ 1 ] = %tp_moon_coverF_crouch_2_run_BL;
|
||||
anim.coverExit[ "crouch" ][ 2 ] = %tp_moon_coverF_crouch_2_run_B;
|
||||
anim.coverExit[ "crouch" ][ 3 ] = %tp_moon_coverF_crouch_2_run_BR;
|
||||
anim.coverExit[ "crouch" ][ 4 ] = %tp_moon_coverF_crouch_2_run_L;
|
||||
anim.coverExit[ "crouch" ][ 6 ] = %tp_moon_coverF_crouch_2_run_R;
|
||||
//im.coverExit[ "crouch" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverExit[ "crouch" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverExit[ "crouch" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "stand" ][ 1 ] = %tp_moon_coverF_stand_2_run_BL;
|
||||
anim.coverExit[ "stand" ][ 2 ] = %tp_moon_coverF_stand_2_run_B;
|
||||
anim.coverExit[ "stand" ][ 3 ] = %tp_moon_coverF_stand_2_run_BR;
|
||||
anim.coverExit[ "stand" ][ 4 ] = %tp_moon_coverF_stand_2_run_L;
|
||||
anim.coverExit[ "stand" ][ 6 ] = %tp_moon_coverF_stand_2_run_R;
|
||||
//im.coverExit[ "stand" ][ 7 ] = can't approach from this direction;
|
||||
//im.coverExit[ "stand" ][ 8 ] = can't approach from this direction;
|
||||
//im.coverExit[ "stand" ][ 9 ] = can't approach from this direction;
|
||||
|
||||
anim.coverExit[ "stand_saw" ][ 1 ] = %saw_gunner_runout_ML;
|
||||
anim.coverExit[ "stand_saw" ][ 2 ] = %saw_gunner_runout_M;
|
||||
anim.coverExit[ "stand_saw" ][ 3 ] = %saw_gunner_runout_MR;
|
||||
anim.coverExit[ "stand_saw" ][ 4 ] = %saw_gunner_runout_L;
|
||||
anim.coverExit[ "stand_saw" ][ 6 ] = %saw_gunner_runout_R;
|
||||
|
||||
// anim.coverExit["prone_saw" ][1] = %saw_gunner_prone_runout_ML;
|
||||
anim.coverExit[ "prone_saw" ][ 2 ] = %saw_gunner_prone_runout_M;
|
||||
// anim.coverExit["prone_saw" ][3] = %saw_gunner_prone_runout_MR;
|
||||
anim.coverExit[ "prone_saw" ][ 4 ] = %saw_gunner_prone_runout_L;
|
||||
anim.coverExit[ "prone_saw" ][ 6 ] = %saw_gunner_prone_runout_R;
|
||||
// anim.coverExit["prone_saw" ][7] = %saw_gunner_prone_runout_F; // need this anim or a way to exclude it
|
||||
anim.coverExit[ "prone_saw" ][ 8 ] = %saw_gunner_prone_runout_F;
|
||||
|
||||
anim.coverExit[ "crouch_saw" ][ 1 ] = %saw_gunner_lowwall_runout_ML;
|
||||
anim.coverExit[ "crouch_saw" ][ 2 ] = %saw_gunner_lowwall_runout_M;
|
||||
anim.coverExit[ "crouch_saw" ][ 3 ] = %saw_gunner_lowwall_runout_MR;
|
||||
anim.coverExit[ "crouch_saw" ][ 4 ] = %saw_gunner_lowwall_runout_L;
|
||||
anim.coverExit[ "crouch_saw" ][ 6 ] = %saw_gunner_lowwall_runout_R;
|
||||
|
||||
// we need 45 degree angle exits for exposed...
|
||||
anim.coverExit[ "exposed" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed" ][ 1 ] = %tp_moon_exposed_stand_2_run_BL;
|
||||
anim.coverExit[ "exposed" ][ 2 ] = %tp_moon_exposed_stand_2_run_B;
|
||||
anim.coverExit[ "exposed" ][ 3 ] = %tp_moon_exposed_stand_2_run_BR;
|
||||
anim.coverExit[ "exposed" ][ 4 ] = %tp_moon_exposed_stand_2_run_L;
|
||||
anim.coverExit[ "exposed" ][ 6 ] = %tp_moon_exposed_stand_2_run_R;
|
||||
anim.coverExit[ "exposed" ][ 7 ] = %tp_moon_exposed_stand_2_run_FL;
|
||||
anim.coverExit[ "exposed" ][ 8 ] = %tp_moon_exposed_stand_2_run_F; // %stand_2_run_F_2;
|
||||
anim.coverExit[ "exposed" ][ 9 ] = %tp_moon_exposed_stand_2_run_FR;
|
||||
|
||||
anim.coverExit[ "exposed_crouch" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_crouch" ][ 1 ] = %tp_moon_exposed_crouch_2_run_BL;
|
||||
anim.coverExit[ "exposed_crouch" ][ 2 ] = %tp_moon_exposed_crouch_2_run_B;
|
||||
anim.coverExit[ "exposed_crouch" ][ 3 ] = %tp_moon_exposed_crouch_2_run_BR;
|
||||
anim.coverExit[ "exposed_crouch" ][ 4 ] = %tp_moon_exposed_crouch_2_run_L;
|
||||
anim.coverExit[ "exposed_crouch" ][ 6 ] = %tp_moon_exposed_crouch_2_run_R;
|
||||
anim.coverExit[ "exposed_crouch" ][ 7 ] = %tp_moon_exposed_crouch_2_run_FL;
|
||||
anim.coverExit[ "exposed_crouch" ][ 8 ] = %tp_moon_exposed_crouch_2_run_F;
|
||||
anim.coverExit[ "exposed_crouch" ][ 9 ] = %tp_moon_exposed_crouch_2_run_FR;
|
||||
|
||||
anim.coverExit[ "exposed_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_cqb" ][ 1 ] = %tp_moon_cqb_exposed_stand_2_run_BL;
|
||||
anim.coverExit[ "exposed_cqb" ][ 2 ] = %tp_moon_cqb_exposed_stand_2_run_B;
|
||||
anim.coverExit[ "exposed_cqb" ][ 3 ] = %tp_moon_cqb_exposed_stand_2_run_BR;
|
||||
anim.coverExit[ "exposed_cqb" ][ 4 ] = %tp_moon_cqb_exposed_stand_2_run_L;
|
||||
anim.coverExit[ "exposed_cqb" ][ 6 ] = %tp_moon_cqb_exposed_stand_2_run_R;
|
||||
anim.coverExit[ "exposed_cqb" ][ 7 ] = %tp_moon_cqb_exposed_stand_2_run_FL;
|
||||
anim.coverExit[ "exposed_cqb" ][ 8 ] = %tp_moon_cqb_exposed_stand_2_run_F;
|
||||
anim.coverExit[ "exposed_cqb" ][ 9 ] = %tp_moon_cqb_exposed_stand_2_run_FR;
|
||||
|
||||
anim.coverExit[ "exposed_crouch_cqb" ] = [];// need this or it chokes on the next line due to assigning undefined...
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 1 ] = %tp_moon_exposed_crouch_2_run_BL;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 2 ] = %tp_moon_exposed_crouch_2_run_B;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 3 ] = %tp_moon_exposed_crouch_2_run_BR;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 4 ] = %tp_moon_exposed_crouch_2_run_L;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 6 ] = %tp_moon_exposed_crouch_2_run_R;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 7 ] = %tp_moon_exposed_crouch_2_run_FL;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 8 ] = %tp_moon_exposed_crouch_2_run_F;
|
||||
anim.coverExit[ "exposed_crouch_cqb" ][ 9 ] = %tp_moon_exposed_crouch_2_run_FR;
|
||||
|
||||
anim.coverExit[ "heat" ] = [];
|
||||
anim.coverExit[ "heat" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat" ][ 6 ] = %heat_exit_6; //%heat_exit_6a
|
||||
anim.coverExit[ "heat" ][ 7 ] = %heat_exit_7;
|
||||
anim.coverExit[ "heat" ][ 8 ] = %heat_exit_8; //%heat_exit_8a
|
||||
anim.coverExit[ "heat" ][ 9 ] = %heat_exit_9;
|
||||
|
||||
anim.coverExit[ "heat_left" ] = [];
|
||||
anim.coverExit[ "heat_left" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat_left" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat_left" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat_left" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat_left" ][ 6 ] = %heat_exit_6;
|
||||
anim.coverExit[ "heat_left" ][ 7 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_left" ][ 8 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_left" ][ 9 ] = %heat_exit_8R;
|
||||
|
||||
anim.coverExit[ "heat_right" ] = [];
|
||||
anim.coverExit[ "heat_right" ][ 1 ] = %heat_exit_1;
|
||||
anim.coverExit[ "heat_right" ][ 2 ] = %heat_exit_2;
|
||||
anim.coverExit[ "heat_right" ][ 3 ] = %heat_exit_3;
|
||||
anim.coverExit[ "heat_right" ][ 4 ] = %heat_exit_4;
|
||||
anim.coverExit[ "heat_right" ][ 6 ] = %heat_exit_6;
|
||||
anim.coverExit[ "heat_right" ][ 7 ] = %heat_exit_8L;
|
||||
anim.coverExit[ "heat_right" ][ 8 ] = %heat_exit_8R;
|
||||
anim.coverExit[ "heat_right" ][ 9 ] = %heat_exit_8R;
|
||||
|
||||
|
||||
for ( i = 1; i <= 6; i++ )
|
||||
{
|
||||
if ( i == 5 )
|
||||
continue;
|
||||
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
if ( isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
{
|
||||
anim.coverTransDist [ trans ][ i ] = getMoveDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
anim.coverTransAngles[ trans ][ i ] = getAngleDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
if ( isdefined( anim.coverExit [ trans ] ) && isdefined( anim.coverExit [ trans ][ i ] ) )
|
||||
{
|
||||
// get exit dist only to code_move
|
||||
if ( animHasNotetrack( anim.coverExit[ trans ][ i ], "code_move" ) )
|
||||
codeMoveTime = getNotetrackTimes( anim.coverExit[ trans ][ i ], "code_move" )[ 0 ];
|
||||
else
|
||||
codeMoveTime = 1;
|
||||
|
||||
anim.coverExitDist [ trans ][ i ] = getMoveDelta( anim.coverExit [ trans ][ i ], 0, codeMoveTime );
|
||||
anim.coverExitAngles [ trans ][ i ] = getAngleDelta( anim.coverExit [ trans ][ i ], 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
anim.coverTransLongestDist[ trans ] = 0;
|
||||
|
||||
for ( i = 1; i <= 6; i++ )
|
||||
{
|
||||
if ( i == 5 || !isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
continue;
|
||||
|
||||
lengthSq = lengthSquared( anim.coverTransDist[ trans ][ i ] );
|
||||
if ( anim.coverTransLongestDist[ trans ] < lengthSq )
|
||||
anim.coverTransLongestDist[ trans ] = lengthSq;
|
||||
}
|
||||
|
||||
anim.coverTransLongestDist[ trans ] = sqrt( anim.coverTransLongestDist[ trans ] );
|
||||
}
|
||||
|
||||
anim.exposedTransition[ "exposed" ] = true;
|
||||
anim.exposedTransition[ "exposed_crouch" ] = true;
|
||||
anim.exposedTransition[ "exposed_cqb" ] = true;
|
||||
anim.exposedTransition[ "exposed_crouch_cqb" ] = true;
|
||||
anim.exposedTransition[ "heat" ] = true;
|
||||
|
||||
anim.longestExposedApproachDist = 0;
|
||||
|
||||
foreach ( trans, transType in anim.exposedTransition )
|
||||
{
|
||||
for ( i = 7; i <= 9; i++ )
|
||||
{
|
||||
if ( isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
{
|
||||
anim.coverTransDist [ trans ][ i ] = getMoveDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
anim.coverTransAngles[ trans ][ i ] = getAngleDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
if ( isdefined( anim.coverExit [ trans ][ i ] ) )
|
||||
{
|
||||
// get exit dist only to code_move
|
||||
assert( animHasNotetrack( anim.coverExit[ trans ][ i ], "code_move" ) );
|
||||
codeMoveTime = getNotetrackTimes( anim.coverExit[ trans ][ i ], "code_move" )[ 0 ];
|
||||
|
||||
anim.coverExitDist [ trans ][ i ] = getMoveDelta( anim.coverExit [ trans ][ i ], 0, codeMoveTime );
|
||||
anim.coverExitAngles [ trans ][ i ] = getAngleDelta( anim.coverExit [ trans ][ i ], 0, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
if ( !isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
continue;
|
||||
|
||||
len = length( anim.coverTransDist[ trans ][ i ] );
|
||||
if ( len > anim.longestExposedApproachDist )
|
||||
anim.longestExposedApproachDist = len;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// the FindBestSplitTime calls below are used to find these values.
|
||||
// all of this is for corner nodes.
|
||||
|
||||
anim.coverTransSplit[ "left" ][ 7 ] = 0.5;// delta of( 35.5356, 3.27114, 0 )
|
||||
anim.coverTransSplit[ "left_crouch" ][ 7 ] = 0.448; // delta of (32.2281, 0.356673, 0)
|
||||
anim.coverTransSplit[ "left_cqb" ][ 7 ] = 0.5; // delta of (33.1115, 1.05645, 0)
|
||||
anim.coverTransSplit[ "left_crouch_cqb" ][ 7 ] = 0.448; // delta of (34.2986, 2.32586, 0)
|
||||
anim.coverExitSplit[ "left" ][ 7 ] = 0.52;// delta of( 37.5652, 5.61999, 0 )
|
||||
anim.coverExitSplit[ "left_crouch" ][ 7 ] = 0.55;// delta of( 35.9166, 3.88091, 0 )
|
||||
anim.coverExitSplit[ "left_cqb" ][ 7 ] = 0.52; // delta of (32.9692, 0.881301, 0)
|
||||
anim.coverExitSplit[ "left_crouch_cqb" ][ 7 ] = 0.55; // delta of (33.6642, 1.70904, 0)
|
||||
anim.coverExitSplit[ "heat_left" ][ 7 ] = 0.42;
|
||||
|
||||
anim.coverTransSplit[ "left" ][ 8 ] = 0.38;// delta of( 32.9863, 0.925748, 0 )
|
||||
anim.coverTransSplit[ "left_crouch" ][ 8 ] = 0.5;// delta of( 38.4125, 6.445, 0 )
|
||||
anim.coverTransSplit[ "left_cqb" ][ 8 ] = 0.38; // delta of (33.892, 1.86121, 0)
|
||||
anim.coverTransSplit[ "left_crouch_cqb" ][ 8 ] = 0.5; // delta of (35.8107, 3.70985, 0)
|
||||
anim.coverExitSplit[ "left" ][ 8 ] = 0.442;// delta of( 34.298, 2.26239, 0 )
|
||||
anim.coverExitSplit[ "left_crouch" ][ 8 ] = 0.6; // delta of (33.0388, 0.964628, 0)
|
||||
anim.coverExitSplit[ "left_cqb" ][ 8 ] = 0.442; // delta of (35.6563, 3.64754, 0))
|
||||
anim.coverExitSplit[ "left_crouch_cqb" ][ 8 ] = 0.6; // delta of (33.0797, 1.14774, 0)
|
||||
anim.coverExitSplit[ "heat_left" ][ 8 ] = 0.42;
|
||||
|
||||
anim.coverTransSplit[ "right" ][ 8 ] = 0.561562;// delta of( 35.6571, 3.63511, 0 )
|
||||
anim.coverTransSplit[ "right_crouch" ][ 8 ] = 0.521522; // delta of (34.6368, 2.67554, 0)
|
||||
anim.coverTransSplit[ "right_cqb" ][ 8 ] = 0.561562; // delta of (35.6571, 3.63511, 0)
|
||||
anim.coverTransSplit[ "right_crouch_cqb" ][ 8 ] = 0.521522; // delta of (34.2736, 2.32471, 0)
|
||||
anim.coverExitSplit[ "right" ][ 8 ] = 0.316316;// delta of( 36.3085, 4.34586, 0 )
|
||||
anim.coverExitSplit[ "right_crouch" ][ 8 ] = 0.386386; // delta of (33.1181, 1.14301, -0.0001)
|
||||
anim.coverExitSplit[ "right_cqb" ][ 8 ] = 0.316316; // delta of (33.0089, 1.0005, 0)
|
||||
anim.coverExitSplit[ "right_crouch_cqb" ][ 8 ] = 0.386386; // delta of (34.7739, 2.41176, 0)
|
||||
anim.coverExitSplit[ "heat_right" ][ 8 ] = 0.4;
|
||||
|
||||
anim.coverTransSplit[ "right" ][ 9 ] = 0.41041;// delta of( 37.7732, 5.76641, 0 )
|
||||
anim.coverTransSplit[ "right_crouch" ][ 9 ] = 0.518519; // delta of (36.3871, 4.39434, 0)
|
||||
anim.coverTransSplit[ "right_cqb" ][ 9 ] = 0.41041;// delta of( 37.7732, 5.76641, 0 )
|
||||
anim.coverTransSplit[ "right_crouch_cqb" ][ 9 ] = 0.232232518519; // delta of (35.8102, 3.81592, 0)
|
||||
anim.coverExitSplit[ "right" ][ 9 ] = 0.365365; // delta of (35.251, 3.31115, 0)
|
||||
anim.coverExitSplit[ "right_crouch" ][ 9 ] = 0.376376; // delta of (34.4959, 2.45688, -0.0001)
|
||||
anim.coverExitSplit[ "right_cqb" ][ 9 ] = 0.365365; // delta of (35.4487, 3.42926, 0)
|
||||
anim.coverExitSplit[ "right_crouch_cqb" ][ 9 ] = 0.376376; // delta of (35.4592, 1.47273, 0)
|
||||
anim.coverExitSplit[ "heat_right" ][ 9 ] = 0.4;
|
||||
|
||||
/#
|
||||
setDvarIfUninitialized( "scr_findsplittimes", "0" );
|
||||
#/
|
||||
|
||||
splitArrivals = [];
|
||||
splitArrivals[ "left" ] = 1;
|
||||
splitArrivals[ "left_crouch" ] = 1;
|
||||
splitArrivals[ "left_crouch_cqb" ] = 1;
|
||||
splitArrivals[ "left_cqb" ] = 1;
|
||||
|
||||
splitExits = [];
|
||||
splitExits[ "left" ] = 1;
|
||||
splitExits[ "left_crouch" ] = 1;
|
||||
splitExits[ "left_crouch_cqb" ] = 1;
|
||||
splitExits[ "left_cqb" ] = 1;
|
||||
splitExits[ "heat_left" ] = 1;
|
||||
|
||||
GetSplitTimes( 7, 8, false, splitArrivals, splitExits );
|
||||
|
||||
|
||||
splitArrivals = [];
|
||||
splitArrivals[ "right" ] = 1;
|
||||
splitArrivals[ "right_crouch" ] = 1;
|
||||
splitArrivals[ "right_cqb" ] = 1;
|
||||
splitArrivals[ "right_crouch_cqb" ] = 1;
|
||||
|
||||
splitExits = [];
|
||||
splitExits[ "right" ] = 1;
|
||||
splitExits[ "right_crouch" ] = 1;
|
||||
splitExits[ "right_cqb" ] = 1;
|
||||
splitExits[ "right_crouch_cqb" ] = 1;
|
||||
splitExits[ "heat_right" ] = 1;
|
||||
|
||||
GetSplitTimes( 8, 9, true, splitArrivals, splitExits );
|
||||
|
||||
|
||||
/#
|
||||
//thread checkApproachAngles( transTypes );
|
||||
#/
|
||||
|
||||
anim.arrivalEndStance["left"] = "stand";
|
||||
anim.arrivalEndStance["left_cqb"] = "stand";
|
||||
anim.arrivalEndStance["right"] = "stand";
|
||||
anim.arrivalEndStance["right_cqb"] = "stand";
|
||||
anim.arrivalEndStance["stand"] = "stand";
|
||||
anim.arrivalEndStance["stand_saw"] = "stand";
|
||||
anim.arrivalEndStance["exposed"] = "stand";
|
||||
anim.arrivalEndStance["exposed_cqb"] = "stand";
|
||||
anim.arrivalEndStance["heat"] = "stand";
|
||||
anim.arrivalEndStance["left_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["left_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["right_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["right_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["crouch_saw"] = "crouch";
|
||||
anim.arrivalEndStance["crouch"] = "crouch";
|
||||
anim.arrivalEndStance["exposed_crouch"] = "crouch";
|
||||
anim.arrivalEndStance["exposed_crouch_cqb"] = "crouch";
|
||||
anim.arrivalEndStance["prone_saw"] = "prone";
|
||||
|
||||
anim.requiredExitStance[ "Cover Stand" ] = "stand";
|
||||
anim.requiredExitStance[ "Conceal Stand" ] = "stand";
|
||||
anim.requiredExitStance[ "Cover Crouch" ] = "crouch";
|
||||
anim.requiredExitStance[ "Conceal Crouch" ] = "crouch";
|
||||
}
|
||||
|
||||
|
||||
GetSplitTimes( begin, end, isRightSide, splitArrivals, splitExits )
|
||||
{
|
||||
for ( i = begin; i <= end; i++ )
|
||||
{
|
||||
foreach ( type, val in splitArrivals )
|
||||
{
|
||||
anim.coverTransPreDist[ type ][ i ] = getMoveDelta( anim.coverTrans[ type ][ i ], 0, getTransSplitTime( type, i ) );
|
||||
anim.coverTransDist [ type ][ i ] = getMoveDelta( anim.coverTrans[ type ][ i ], 0, 1 ) - anim.coverTransPreDist[ type ][ i ];
|
||||
anim.coverTransAngles [ type ][ i ] = getAngleDelta( anim.coverTrans[ type ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
foreach ( type, val in splitExits )
|
||||
{
|
||||
anim.coverExitDist [ type ][ i ] = getMoveDelta( anim.coverExit [ type ][ i ], 0, getExitSplitTime( type, i ) );
|
||||
anim.coverExitPostDist[ type ][ i ] = getMoveDelta( anim.coverExit [ type ][ i ], 0, 1 ) - anim.coverExitDist[ type ][ i ];
|
||||
anim.coverExitAngles [ type ][ i ] = getAngleDelta( anim.coverExit [ type ][ i ], 0, 1 );
|
||||
}
|
||||
|
||||
/#
|
||||
if ( getdebugdvar( "scr_findsplittimes" ) != "0" )
|
||||
{
|
||||
foreach ( type, val in splitArrivals )
|
||||
{
|
||||
if ( isSubStr( type, "heat" ) )
|
||||
continue;
|
||||
|
||||
FindBestSplitTime( anim.coverTrans[ type ][ i ], true, isRightSide, "anim.coverTransSplit[ \"" + type + "\" ][ " + i + " ]", type + " arrival in dir " + i );
|
||||
AssertIsValidSplitDelta( DeltaRotate( anim.coverTransDist[ type ][ i ], 180 - anim.coverTransAngles[ type ][ i ] ), isRightSide, type + " arrival in dir " + i );
|
||||
}
|
||||
|
||||
foreach ( type, val in splitExits )
|
||||
{
|
||||
if ( isSubStr( type, "heat" ) )
|
||||
continue;
|
||||
|
||||
FindBestSplitTime( anim.coverExit [ type ][ i ], false, isRightSide, "anim.coverExitSplit[ \"" + type + "\" ][ " + i + " ]", type + " exit in dir " + i );
|
||||
AssertIsValidSplitDelta( anim.coverExitDist[ type ][ i ], isRightSide, type + " exit in dir " + i );
|
||||
}
|
||||
}
|
||||
#/
|
||||
}
|
||||
}
|
||||
|
||||
/#
|
||||
FindBestSplitTime( exitanim, isapproach, isright, arrayname, debugname )
|
||||
{
|
||||
angleDelta = getAngleDelta( exitanim, 0, 1 );
|
||||
fullDelta = getMoveDelta( exitanim, 0, 1 );
|
||||
numiter = 1000;
|
||||
|
||||
bestsplit = -1;
|
||||
bestvalue = -100000000;
|
||||
bestdelta = ( 0, 0, 0 );
|
||||
|
||||
for ( i = 0; i < numiter; i++ )
|
||||
{
|
||||
splitTime = 1.0 * i / ( numiter - 1 );
|
||||
|
||||
delta = getMoveDelta( exitanim, 0, splitTime );
|
||||
if ( isapproach )
|
||||
delta = DeltaRotate( fullDelta - delta, 180 - angleDelta );
|
||||
if ( isright )
|
||||
delta = ( delta[ 0 ], 0 - delta[ 1 ], delta[ 2 ] );
|
||||
|
||||
val = min( delta[ 0 ] - 32, delta[ 1 ] );
|
||||
|
||||
if ( val > bestvalue || bestsplit < 0 )
|
||||
{
|
||||
bestvalue = val;
|
||||
bestsplit = splitTime;
|
||||
bestdelta = delta;
|
||||
}
|
||||
}
|
||||
|
||||
if ( bestdelta[ 0 ] < 32 || bestdelta[ 1 ] < 0 )
|
||||
{
|
||||
println( "^0 ^1" + debugname + " has no valid split time available! Best was at " + bestsplit + ", delta of " + bestdelta );
|
||||
return;
|
||||
}
|
||||
//println("^0 ^2" + debugname + " has best split time at " + bestsplit + ", delta of " + bestdelta );
|
||||
println( "^0 ^2" + arrayname + " = " + bestsplit + "; // delta of " + bestdelta );
|
||||
}
|
||||
|
||||
|
||||
DeltaRotate( delta, yaw )
|
||||
{
|
||||
cosine = cos( yaw );
|
||||
sine = sin( yaw );
|
||||
return( delta[ 0 ] * cosine - delta[ 1 ] * sine, delta[ 1 ] * cosine + delta[ 0 ] * sine, 0 );
|
||||
}
|
||||
|
||||
AssertIsValidSplitDelta( delta, isRightSide, debugname )
|
||||
{
|
||||
if ( isRightSide )
|
||||
delta = ( delta[ 0 ], 0 - delta[ 1 ], delta[ 2 ] );
|
||||
|
||||
// in a delta, x is forward and y is left
|
||||
|
||||
// assert the delta goes out far enough from the node
|
||||
if ( delta[ 0 ] < 32 )
|
||||
println( "^0 ^1" + debugname + " doesn't go out from the node far enough in the given split time (delta = " + delta + ")" );
|
||||
|
||||
// assert the delta doesn't go into the wall
|
||||
if ( delta[ 1 ] < 0 )
|
||||
println( "^0 ^1" + debugname + " goes into the wall during the given split time (delta = " + delta + ")" );
|
||||
}
|
||||
|
||||
checkApproachAngles( transTypes )
|
||||
{
|
||||
idealTransAngles[ 1 ] = 45;
|
||||
idealTransAngles[ 2 ] = 0;
|
||||
idealTransAngles[ 3 ] = -45;
|
||||
idealTransAngles[ 4 ] = 90;
|
||||
idealTransAngles[ 6 ] = -90;
|
||||
idealTransAngles[ 7 ] = 135;
|
||||
idealTransAngles[ 8 ] = 180;
|
||||
idealTransAngles[ 9 ] = -135;
|
||||
|
||||
wait .05;
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
idealAdd = 0;
|
||||
if ( trans == "left" || trans == "left_crouch" )
|
||||
idealAdd = 90;
|
||||
else if ( trans == "right" || trans == "right_crouch" )
|
||||
idealAdd = -90;
|
||||
|
||||
if ( isdefined( anim.coverTransAngles[ trans ][ i ] ) )
|
||||
{
|
||||
correctAngle = AngleClamp180( idealTransAngles[ i ] + idealAdd );
|
||||
actualAngle = AngleClamp180( anim.coverTransAngles[ trans ][ i ] );
|
||||
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
|
||||
{
|
||||
println( "^1Cover approach animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
for ( j = 0; j < transTypes.size; j++ )
|
||||
{
|
||||
trans = transTypes[ j ];
|
||||
|
||||
idealAdd = 0;
|
||||
if ( trans == "left" || trans == "left_crouch" )
|
||||
idealAdd = 90;
|
||||
else if ( trans == "right" || trans == "right_crouch" )
|
||||
idealAdd = -90;
|
||||
|
||||
if ( isdefined( anim.coverExitAngles[ trans ][ i ] ) )
|
||||
{
|
||||
correctAngle = AngleClamp180( -1 * ( idealTransAngles[ i ] + idealAdd + 180 ) );
|
||||
actualAngle = AngleClamp180( anim.coverExitAngles[ trans ][ i ] );
|
||||
if ( AbsAngleClamp180( actualAngle - correctAngle ) > 7 )
|
||||
{
|
||||
println( "^1Cover exit animation has bad yaw delta: anim.coverTrans[\"" + trans + "\"][" + i + "]; is ^2" + actualAngle + "^1, should be closer to ^2" + correctAngle + "^1." );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#/
|
||||
|
||||
getExitSplitTime( approachType, dir )
|
||||
{
|
||||
exitAnim = anim.coverExit[ approachType ][ dir ];
|
||||
if ( animHasNotetrack( exitAnim, "split_time" ) )
|
||||
{
|
||||
exitAlignTimes = getNotetrackTimes( exitAnim, "split_time" );
|
||||
|
||||
assert( exitAlignTimes.size == 1 );
|
||||
if ( exitAlignTimes.size == 0 )
|
||||
{
|
||||
return anim.coverExitSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
return exitAlignTimes[0];
|
||||
}
|
||||
|
||||
return anim.coverExitSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
getTransSplitTime( approachType, dir )
|
||||
{
|
||||
arrivalAnim = anim.coverTrans[ approachType ][ dir ];
|
||||
if ( animHasNotetrack( arrivalAnim, "split_time" ) )
|
||||
{
|
||||
arrivalSplitTimes = getNotetrackTimes( arrivalAnim, "split_time" );
|
||||
|
||||
assert( arrivalSplitTimes.size == 1 );
|
||||
if ( arrivalSplitTimes.size == 0 )
|
||||
{
|
||||
return anim.coverTransSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
return arrivalSplitTimes[0];
|
||||
}
|
||||
|
||||
return anim.coverTransSplit[ approachType ][ dir ];
|
||||
}
|
||||
|
||||
init_moon_transition_points()
|
||||
{
|
||||
anim.run_transition_notes = [];
|
||||
anim.run_transition_points = [];
|
||||
|
||||
anim.run_transition_notes[ anim.run_transition_notes.size ] = "move_transition_run_r_down";
|
||||
anim.run_transition_points[ anim.run_transition_points.size ] = 0.2537;
|
||||
|
||||
anim.run_transition_notes[ anim.run_transition_notes.size ] = "move_transition_run_l_down";
|
||||
anim.run_transition_points[ anim.run_transition_points.size ] = 0.5074;
|
||||
|
||||
anim.cqb_transition_notes = [];
|
||||
anim.cqb_transition_points = [];
|
||||
|
||||
//entrance for starting the loop at a run with the right foot down
|
||||
anim.cqb_transition_notes[ anim.cqb_transition_notes.size ] = "move_transition_run_r_down";
|
||||
anim.cqb_transition_points[ anim.cqb_transition_points.size ] = 0.48;
|
||||
|
||||
anim.cqb_transition_notes[ anim.cqb_transition_notes.size ] = "move_transition_run_l_down";
|
||||
anim.cqb_transition_points[ anim.cqb_transition_points.size ] = 0.24;
|
||||
|
||||
anim.cqb_transition_notes[ anim.cqb_transition_notes.size ] = "move_transition_start 2";
|
||||
anim.cqb_transition_points[ anim.cqb_transition_points.size ] = 0.6;
|
||||
}
|
||||
|
1748
animscripts/melee.gsc
Normal file
1748
animscripts/melee.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1231
animscripts/move.gsc
Normal file
1231
animscripts/move.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1614
animscripts/pain.gsc
Normal file
1614
animscripts/pain.gsc
Normal file
File diff suppressed because it is too large
Load Diff
396
animscripts/reactions.gsc
Normal file
396
animscripts/reactions.gsc
Normal file
@ -0,0 +1,396 @@
|
||||
#include animscripts\SetPoseMovement;
|
||||
#include animscripts\Utility;
|
||||
#include common_scripts\Utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
animscripts\utility::initialize( "reactions" );
|
||||
|
||||
self newEnemySurprisedReaction();
|
||||
}
|
||||
|
||||
getReactionAnim( name )
|
||||
{
|
||||
if ( IsDefined( self.customCoverReactions ) && IsDefined( self.customCoverReactions[ name ] ) )
|
||||
{
|
||||
return self.customCoverReactions[ name ];
|
||||
}
|
||||
else
|
||||
{
|
||||
return anim.reactionAnimArray[ name ];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
reactionsCheckLoop()
|
||||
{
|
||||
self thread bulletWhizbyCheckLoop();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// death reactions
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/* disabled for now since the animations aren't in common csv
|
||||
|
||||
MoveDeathReaction()
|
||||
{
|
||||
// Decide what pose to use
|
||||
desiredPose = self animscripts\utility::choosePose();
|
||||
|
||||
if ( desiredPose == "stand" )
|
||||
{
|
||||
deathAnim = getDeathReactionAnim();
|
||||
DoDeathReactionAnim( deathAnim );
|
||||
}
|
||||
}
|
||||
|
||||
ExposedCombatDeathReaction()
|
||||
{
|
||||
// Decide what pose to use
|
||||
desiredPose = self animscripts\utility::choosePose();
|
||||
|
||||
if ( desiredPose == "stand" )
|
||||
{
|
||||
deathAnim = getDeathReactionAnim();
|
||||
DoDeathReactionAnim( deathAnim );
|
||||
}
|
||||
}
|
||||
|
||||
DoDeathReactionAnim( deathAnim )
|
||||
{
|
||||
self endon( "movemode" );
|
||||
|
||||
rate = self.moveplaybackrate;
|
||||
|
||||
self setFlaggedAnimKnobAll( "deathanim", deathAnim, %body, 1, 1, rate, true );
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "deathanim" );
|
||||
self.deathTeamate = false;
|
||||
}
|
||||
|
||||
getDeathReactionAnim()
|
||||
{
|
||||
if ( self.deathTeamateReaction == "back" )
|
||||
return %run_reaction_180;
|
||||
else if ( self.deathTeamateReaction == "left" )
|
||||
return %run_reaction_L_quick;
|
||||
else if ( self.deathTeamateReaction == "right" )
|
||||
return %run_reaction_R_quick;
|
||||
}
|
||||
|
||||
deathCheck()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self.deathTeamateReaction = "none";
|
||||
self.deathTeamate = false;
|
||||
|
||||
minDeathDistance = 100;
|
||||
maxDeathDistance = 500;
|
||||
minGoalDistance = 200;
|
||||
maxTurnAngle = 135;
|
||||
minTurnAngle = 10;
|
||||
|
||||
self AddAIEventListener( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "ai_event", event, originator, position );
|
||||
if ( event != "death" )
|
||||
continue;
|
||||
|
||||
deathDirection = position - self.origin;
|
||||
deathDistance = Length( deathDirection );
|
||||
if ( deathDistance >= minDeathDistance && deathDistance <= maxDeathDistance )
|
||||
{
|
||||
goalDirection = self.goalpos - self.origin;
|
||||
goalDistance = Length( goalDirection );
|
||||
if ( goalDistance >= minGoalDistance )
|
||||
{
|
||||
goalAngles = VectorToAngles( goalDirection );
|
||||
deltaAngles = Abs( self.angles[1] - goalAngles[1] );
|
||||
if ( deltaAngles > minTurnAngle )
|
||||
{
|
||||
if ( deltaAngles > maxTurnAngle )
|
||||
self.deathTeamateReaction = "back";
|
||||
else if ( self.angles[1] > goalAngles[1] )
|
||||
self.deathTeamateReaction = "left";
|
||||
else
|
||||
self.deathTeamateReaction = "right";
|
||||
|
||||
self.deathTeamate = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
canReactAgain()
|
||||
{
|
||||
return ( !isdefined( self.lastReactTime ) || gettime() - self.lastReactTime > 2000 );
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// bullet whizby reaction
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bulletWhizbyReaction()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self.lastReactTime = gettime();
|
||||
self.a.movement = "stop";
|
||||
|
||||
enemyNear = ( isDefined( self.whizbyEnemy ) && distanceSquared( self.origin, self.whizbyEnemy.origin ) < 400 * 400 );
|
||||
|
||||
self animmode( "gravity" );
|
||||
self orientmode( "face current" );
|
||||
|
||||
// react and go to prone
|
||||
if ( enemyNear || cointoss() )
|
||||
{
|
||||
self clearanim( %root, 0.1 );
|
||||
|
||||
reactionAnims = getReactionAnim( "wizby_idle" );
|
||||
|
||||
reaction = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
|
||||
if ( enemyNear )
|
||||
waitTime = 1 + randomfloat( 0.5 );
|
||||
else
|
||||
waitTime = 0.2 + randomfloat( 0.5 );
|
||||
|
||||
self setFlaggedAnimKnobRestart( "reactanim", reaction, 1, 0.1, 1 );
|
||||
self animscripts\shared::DoNoteTracksForTime( waitTime, "reactanim" );
|
||||
|
||||
self clearanim( %root, 0.1 );
|
||||
|
||||
if ( !enemyNear && self.stairsState == "none" )
|
||||
{
|
||||
rate = 1 + randomfloat( 0.2 );
|
||||
|
||||
reactionAnims = getReactionAnim( "wizby_dive" );
|
||||
|
||||
diveAnim = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
|
||||
self setFlaggedAnimKnobRestart( "dive", diveAnim, 1, 0.1, rate );
|
||||
self animscripts\shared::DoNoteTracks( "dive" );
|
||||
}
|
||||
}
|
||||
else // crouch then handsignal or turn
|
||||
{
|
||||
wait randomfloat( 0.2 );
|
||||
|
||||
rate = 1.2 + randomfloat( 0.3 );
|
||||
|
||||
if ( self.a.pose == "stand" )
|
||||
{
|
||||
self clearanim( %root, 0.1 );
|
||||
reactionAnim = getReactionAnim( "wizby_crouch" );
|
||||
self setFlaggedAnimKnobRestart( "crouch", reactionAnim, 1, 0.1, rate );
|
||||
self animscripts\shared::DoNoteTracks( "crouch" );
|
||||
}
|
||||
|
||||
forward = anglesToForward( self.angles );
|
||||
|
||||
if ( isDefined( self.whizbyEnemy ) )
|
||||
dirToEnemy = vectorNormalize( self.whizbyEnemy.origin - self.origin );
|
||||
else
|
||||
dirToEnemy = forward;
|
||||
|
||||
if ( vectordot( dirToEnemy, forward ) > 0 )
|
||||
{
|
||||
reactionAnims = getReactionAnim( "wizby_twitch" );
|
||||
twitchAnim = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
|
||||
self clearanim( %root, 0.1 );
|
||||
self setFlaggedAnimKnobRestart( "twitch", twitchAnim, 1, 0.1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "twitch" );
|
||||
|
||||
//if ( cointoss() )
|
||||
// self handsignal( "go" );
|
||||
}
|
||||
else
|
||||
{
|
||||
reactionAnims = getReactionAnim( "wizby_turn" );
|
||||
turnAnim = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
|
||||
self clearanim( %root, 0.1 );
|
||||
self setFlaggedAnimKnobRestart( "turn", turnAnim, 1, 0.1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "turn" );
|
||||
}
|
||||
}
|
||||
|
||||
self clearanim( %root, 0.1 );
|
||||
self.whizbyEnemy = undefined;
|
||||
self animmode( "normal" );
|
||||
self orientmode( "face default" );
|
||||
}
|
||||
|
||||
|
||||
bulletWhizbyCheckLoop()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
if ( isdefined( self.disableBulletWhizbyReaction ) )
|
||||
return;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "bulletwhizby", shooter );
|
||||
|
||||
if ( !isdefined( shooter.team ) || self.team == shooter.team )
|
||||
continue;
|
||||
|
||||
if ( isdefined( self.coverNode ) || isdefined( self.ambushNode ) )
|
||||
continue;
|
||||
|
||||
if ( self.a.pose != "stand" )
|
||||
continue;
|
||||
|
||||
if ( !canReactAgain() )
|
||||
continue;
|
||||
|
||||
self.whizbyEnemy = shooter;
|
||||
self animcustom( ::bulletWhizbyReaction );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// surprised by new enemy reaction
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
clearLookAtThread()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
wait 0.3;
|
||||
self setLookAtEntity();
|
||||
}
|
||||
|
||||
|
||||
getNewEnemyReactionAnim()
|
||||
{
|
||||
reactAnim = undefined;
|
||||
|
||||
if ( self nearClaimNodeAndAngle() && isdefined( anim.reactionAnimArray[ self.prevScript ] ) )
|
||||
{
|
||||
nodeForward = anglesToForward( self.node.angles );
|
||||
dirToReactionTarget = vectorNormalize( self.reactionTargetPos - self.origin );
|
||||
|
||||
if ( vectorDot( nodeForward, dirToReactionTarget ) < -0.5 )
|
||||
{
|
||||
self orientmode( "face current" );
|
||||
reactionAnims = getReactionAnim( self.prevScript );
|
||||
reactAnim = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
}
|
||||
}
|
||||
|
||||
if ( !isdefined( reactAnim ) )
|
||||
{
|
||||
if ( isdefined( self.enemy ) && distanceSquared( self.enemy.origin, self.reactionTargetPos ) < 256 * 256 )
|
||||
self orientmode( "face enemy" );
|
||||
else
|
||||
self orientmode( "face point", self.reactionTargetPos );
|
||||
|
||||
if ( self.a.pose == "crouch" )
|
||||
{
|
||||
dirToReactionTarget = vectorNormalize( self.reactionTargetPos - self.origin );
|
||||
forward = anglesToForward( self.angles );
|
||||
if ( vectorDot( forward, dirToReactionTarget ) < -0.5 )
|
||||
{
|
||||
self orientmode( "face current" );
|
||||
reactionAnims = getReactionAnim( "crouch" );
|
||||
return reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
}
|
||||
}
|
||||
|
||||
reactionAnims = getReactionAnim( "stand" );
|
||||
reactAnim = reactionAnims[ randomint( reactionAnims.size ) ];
|
||||
}
|
||||
|
||||
return reactAnim;
|
||||
}
|
||||
|
||||
|
||||
stealthNewEnemyReactAnim()
|
||||
{
|
||||
self clearanim( %root, 0.2 );
|
||||
|
||||
if ( randomint( 4 ) < 3 )
|
||||
{
|
||||
self orientmode( "face enemy" );
|
||||
self setFlaggedAnimKnobRestart( "reactanim", getReactionAnim( "stealth" ), 1, 0.2, 1 );
|
||||
time = getAnimLength( getReactionAnim( "stealth" ) );
|
||||
self animscripts\shared::DoNoteTracksForTime( time * 0.8, "reactanim" );
|
||||
|
||||
self orientmode( "face current" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self orientmode( "face enemy" );
|
||||
self setFlaggedAnimKnobRestart( "reactanim", getReactionAnim( "stealth_backpedal" ), 1, 0.2, 1 );
|
||||
time = getAnimLength( getReactionAnim( "stealth_backpedal" ) );
|
||||
self animscripts\shared::DoNoteTracksForTime( time * 0.8, "reactanim" );
|
||||
|
||||
self orientmode( "face current" );
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
self setFlaggedAnimKnobRestart( "reactanim", getReactionAnim( "stealth_backpedal2" ), 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "reactanim" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
newEnemyReactionAnim()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "endNewEnemyReactionAnim" );
|
||||
|
||||
self.lastReactTime = gettime();
|
||||
self.a.movement = "stop";
|
||||
|
||||
if ( isdefined( self._stealth ) && self.alertLevel != "combat" )
|
||||
{
|
||||
stealthNewEnemyReactAnim();
|
||||
}
|
||||
else
|
||||
{
|
||||
reactAnim = self getNewEnemyReactionAnim();
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
self setFlaggedAnimKnobRestart( "reactanim", reactAnim, 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "reactanim" );
|
||||
}
|
||||
|
||||
self notify( "newEnemyReactionDone" );
|
||||
}
|
||||
|
||||
|
||||
newEnemySurprisedReaction()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( isdefined( self.disableReactionAnims ) )
|
||||
return;
|
||||
|
||||
if ( !canReactAgain() )
|
||||
return;
|
||||
|
||||
if ( self.a.pose == "prone" || isdefined( self.a.onback ) )
|
||||
return;
|
||||
|
||||
self animmode( "gravity" );
|
||||
|
||||
if ( isdefined( self.enemy ) )
|
||||
newEnemyReactionAnim();
|
||||
}
|
801
animscripts/riotshield/riotshield.gsc
Normal file
801
animscripts/riotshield/riotshield.gsc
Normal file
@ -0,0 +1,801 @@
|
||||
#include maps\_utility;
|
||||
#include animscripts\utility;
|
||||
#include animscripts\Combat_utility;
|
||||
#include animscripts\melee;
|
||||
#include common_scripts\utility;
|
||||
|
||||
RIOTSHIELD_FACE_ENEMY_DIST = 1500;
|
||||
RIOTSHIELD_FORCE_WALK_DIST = 500;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
init_riotshield_AI_anims()
|
||||
{
|
||||
anim.notetracks[ "detach shield" ] = ::noteTrackDetachShield;
|
||||
|
||||
animscripts\init_move_transitions::init_move_transition_arrays();
|
||||
|
||||
anim.coverTrans[ "riotshield" ] = [];
|
||||
anim.coverTrans[ "riotshield" ][ 1 ] = %riotshield_run_approach_1;
|
||||
anim.coverTrans[ "riotshield" ][ 2 ] = %riotshield_run_approach_2;
|
||||
anim.coverTrans[ "riotshield" ][ 3 ] = %riotshield_run_approach_3;
|
||||
anim.coverTrans[ "riotshield" ][ 4 ] = %riotshield_run_approach_4;
|
||||
anim.coverTrans[ "riotshield" ][ 6 ] = %riotshield_run_approach_6;
|
||||
anim.coverTrans[ "riotshield" ][ 7 ] = undefined;
|
||||
anim.coverTrans[ "riotshield" ][ 8 ] = %riotshield_walk2crouch_8;
|
||||
anim.coverTrans[ "riotshield" ][ 9 ] = undefined;
|
||||
|
||||
anim.coverTrans[ "riotshield_crouch" ] = [];
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 1 ] = %riotshield_walk_approach_1;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 2 ] = %riotshield_walk_approach_2;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 3 ] = %riotshield_walk_approach_3;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 4 ] = %riotshield_walk_approach_4;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 6 ] = %riotshield_walk_approach_6;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 7 ] = undefined;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 8 ] = %riotshield_walk2crouch_8;
|
||||
anim.coverTrans[ "riotshield_crouch" ][ 9 ] = undefined;
|
||||
|
||||
riotshieldTransTypes = [];
|
||||
riotshieldTransTypes[0] = "riotshield";
|
||||
riotshieldTransTypes[1] = "riotshield_crouch";
|
||||
|
||||
for ( j = 0; j < riotshieldTransTypes.size; j++ )
|
||||
{
|
||||
trans = riotshieldTransTypes[ j ];
|
||||
|
||||
for ( i = 1; i <= 9; i++ )
|
||||
{
|
||||
if ( i == 5 )
|
||||
continue;
|
||||
|
||||
if ( isdefined( anim.coverTrans[ trans ][ i ] ) )
|
||||
{
|
||||
anim.coverTransDist [ trans ][ i ] = getMoveDelta( anim.coverTrans[ trans ][ i ], 0, 1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 1 ] = 45;
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 2 ] = 0;
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 3 ] = -45;
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 4 ] = 90;
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 6 ] = -90;
|
||||
anim.coverTransAngles[ "riotshield_crouch" ][ 8 ] = 180;
|
||||
|
||||
anim.coverTransAngles[ "riotshield" ][ 1 ] = 45;
|
||||
anim.coverTransAngles[ "riotshield" ][ 2 ] = 0;
|
||||
anim.coverTransAngles[ "riotshield" ][ 3 ] = -45;
|
||||
anim.coverTransAngles[ "riotshield" ][ 4 ] = 90;
|
||||
anim.coverTransAngles[ "riotshield" ][ 6 ] = -90;
|
||||
anim.coverTransAngles[ "riotshield" ][ 8 ] = 180;
|
||||
|
||||
anim.arrivalEndStance[ "riotshield" ] = "crouch";
|
||||
anim.arrivalEndStance[ "riotshield_crouch" ] = "crouch";
|
||||
|
||||
|
||||
animscripts\init_common::addGrenadeThrowAnimOffset( %riotshield_crouch_grenade_toss, (-3.20014, 1.7098, 55.6886) );
|
||||
}
|
||||
|
||||
noteTrackDetachShield( note, flagName )
|
||||
{
|
||||
self animscripts\shared::DropAIWeapon( self.secondaryWeapon );
|
||||
self.secondaryWeapon = "none";
|
||||
|
||||
if ( isAlive( self ) )
|
||||
riotshield_turn_into_regular_ai();
|
||||
}
|
||||
|
||||
riotshield_approach_type()
|
||||
{
|
||||
if ( self.a.pose == "crouch" )
|
||||
return "riotshield_crouch";
|
||||
|
||||
return "riotshield";
|
||||
}
|
||||
|
||||
riotshield_approach_conditions( node )
|
||||
{
|
||||
// to allow approach while facing enemy and crouch walking
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
init_riotshield_AI()
|
||||
{
|
||||
//shieldModel = getWeaponModel( self.secondaryWeapon );
|
||||
//self attach( shieldModel, "tag_weapon_left" );
|
||||
|
||||
animscripts\shared::placeWeaponOn( self.secondaryWeapon, "left", false );
|
||||
|
||||
self.subclass = "riotshield"; // incase guy didn't spawn as a "riotshield" ai
|
||||
|
||||
self.approachTypeFunc = ::riotshield_approach_type;
|
||||
self.approachConditionCheckFunc = ::riotshield_approach_conditions;
|
||||
|
||||
self.faceEnemyArrival = true;
|
||||
self.disableCoverArrivalsOnly = true;
|
||||
self.pathRandomPercent = 0;
|
||||
self.interval = 0;
|
||||
self.disableDoorBehavior = true;
|
||||
self.no_pistol_switch = true;
|
||||
self.dontShootWhileMoving = true;
|
||||
self.disableBulletWhizbyReaction = true;
|
||||
self.disableFriendlyFireReaction = true;
|
||||
self.neverSprintForVariation = true;
|
||||
self.combatMode = "no_cover";
|
||||
self.fixednode = false;
|
||||
self.maxFaceEnemyDist = RIOTSHIELD_FACE_ENEMY_DIST;
|
||||
self.noMeleeChargeDelay = true;
|
||||
self.meleeChargeDistSq = squared( 256 );
|
||||
self.meleePlayerWhileMoving = true;
|
||||
self.useMuzzleSideOffset = true;
|
||||
|
||||
// fall over after getting hit this many times on the shield all within 0.3 seconds of each other
|
||||
if ( level._gameSkill < 1 )
|
||||
self.shieldBulletBlockLimit = randomintrange( 4, 8 );
|
||||
else
|
||||
self.shieldBulletBlockLimit = randomintrange( 8, 12 );
|
||||
|
||||
self.shieldBulletBlockCount = 0;
|
||||
self.shieldBulletBlockTime = 0;
|
||||
|
||||
self.walkDist = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
self.walkDistFacingMotion = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
|
||||
self.grenadeAwareness = 1;
|
||||
self.frontShieldAngleCos = 0.5;
|
||||
self.noGrenadeReturnThrow = true;
|
||||
self.a.grenadeThrowPose = "crouch";
|
||||
self.minExposedGrenadeDist = 400;
|
||||
|
||||
self.ignoresuppression = true;
|
||||
|
||||
self.specialMelee_Standard = ::riotshield_melee_standard;
|
||||
self.specialMeleeChooseAction = ::riotshield_melee_AIvsAI;
|
||||
|
||||
self disable_turnAnims();
|
||||
self disable_surprise();
|
||||
self disable_cqbwalk();
|
||||
|
||||
init_riotshield_animsets();
|
||||
|
||||
if ( level._gameSkill < 1 )
|
||||
self.bullet_resistance = 30;
|
||||
else
|
||||
self.bullet_resistance = 40;
|
||||
|
||||
self add_damage_function( maps\_spawner::bullet_resistance );
|
||||
self add_damage_function( animscripts\pain::additive_pain );
|
||||
}
|
||||
|
||||
|
||||
riotshield_charge()
|
||||
{
|
||||
if ( !Melee_Standard_UpdateAndValidateTarget() )
|
||||
return false;
|
||||
|
||||
// get from animation
|
||||
delta = getMoveDelta( %riotshield_bashA_attack, 0, 1 );
|
||||
rangeSq = lengthSquared( delta );
|
||||
|
||||
if ( distanceSquared( self.origin, self.melee.target.origin ) < rangeSq )
|
||||
return true;
|
||||
|
||||
self animscripts\melee::Melee_PlayChargeSound();
|
||||
|
||||
sampleTime = 0.1;
|
||||
firstTry = true;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
assert( isdefined( self.melee.target ) );
|
||||
|
||||
// now that we moved a bit, see if our target moved before we check for valid melee
|
||||
// it's possible something happened in the meantime that makes meleeing impossible.
|
||||
if ( !Melee_Standard_UpdateAndValidateTarget() )
|
||||
return false;
|
||||
|
||||
if ( firstTry )
|
||||
{
|
||||
self.a.pose = "stand";
|
||||
self SetFlaggedAnimKnobAll( "chargeanim", %riotshield_sprint, %body, 1, .2, 1 );
|
||||
firstTry = false;
|
||||
}
|
||||
|
||||
self orientMode( "face point", self.melee.target.origin );
|
||||
self animscripts\shared::DoNoteTracksForTime( sampleTime, "chargeanim" );
|
||||
|
||||
enemyDistanceSq = distanceSquared( self.origin, self.melee.target.origin );
|
||||
|
||||
// if we're done raising our gun, and starting a melee now will hit the guy, our preparation is finished
|
||||
if ( enemyDistanceSq < rangeSq )
|
||||
break;
|
||||
|
||||
// don't keep charging if we've been doing this for too long.
|
||||
if ( gettime() >= self.melee.giveUpTime )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
riotshield_melee_standard()
|
||||
{
|
||||
self animMode( "zonly_physics" );
|
||||
|
||||
animscripts\melee::Melee_Standard_ResetGiveUpTime();
|
||||
|
||||
while ( true )
|
||||
{
|
||||
if ( !riotshield_charge() )
|
||||
{
|
||||
// if we couldn't get in place to melee, don't try to charge for a little while and abort
|
||||
self.nextMeleeChargeTime = getTime() + 1500;
|
||||
self.nextMeleeChargeTarget = self.melee.target;
|
||||
break;
|
||||
}
|
||||
|
||||
assert( (self.a.pose == "stand") || (self.a.pose == "crouch") );
|
||||
|
||||
self animscripts\battleChatter_ai::evaluateMeleeEvent();
|
||||
|
||||
self orientMode( "face point", self.melee.target.origin );
|
||||
self setflaggedanimknoballrestart( "meleeanim", %riotshield_bash_vs_player, %body, 1, .2, 1 );
|
||||
|
||||
self.melee.inProgress = true;
|
||||
|
||||
// If the attack loop returns false, we need to stop this melee
|
||||
if( !animscripts\melee::Melee_Standard_PlayAttackLoop() )
|
||||
{
|
||||
// Since getting here means that we've done a melee but our attack is no longer valid, delay before we can do a standard attack again.
|
||||
animscripts\melee::Melee_Standard_DelayStandardCharge( self.melee.target );
|
||||
break;
|
||||
}
|
||||
|
||||
self animMode( "none" );
|
||||
}
|
||||
|
||||
self animMode( "none" );
|
||||
}
|
||||
|
||||
riotshield_melee_AIvsAI()
|
||||
{
|
||||
assert( isDefined( self ) );
|
||||
assert( isDefined( self.melee.target ) );
|
||||
|
||||
target = self.melee.target;
|
||||
|
||||
animscripts\melee::Melee_Decide_Winner();
|
||||
|
||||
// Choose which sequence to play based on angles
|
||||
angleToEnemy = vectortoangles( target.origin - self.origin );
|
||||
angleDiff = AngleClamp180( target.angles[ 1 ] - angleToEnemy[ 1 ] );
|
||||
|
||||
if ( abs( angleDiff ) > 100 ) // facing each other
|
||||
{
|
||||
if ( self.melee.winner )
|
||||
{
|
||||
if ( self.subclass == "riotshield" )
|
||||
{
|
||||
self.melee.animName = %riotshield_bashA_attack;
|
||||
target.melee.animName = %riotshield_bashA_defend;
|
||||
target.melee.surviveAnimName = %riotshield_bashA_defend_survive;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( target.subclass == "riotshield" );
|
||||
self.melee.animName = %riotshield_bashB_defend;
|
||||
target.melee.animName = %riotshield_bashB_attack;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( self.subclass == "riotshield" )
|
||||
{
|
||||
self.melee.animName = %riotshield_bashB_attack;
|
||||
target.melee.animName = %riotshield_bashB_defend;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( target.subclass == "riotshield" );
|
||||
self.melee.animName = %riotshield_bashA_defend;
|
||||
target.melee.animName = %riotshield_bashA_attack;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
self.melee.startPos = getStartOrigin( target.origin, target.angles, self.melee.animName );
|
||||
self.melee.startAngles = ( target.angles[0], AngleClamp180( target.angles[1] + 180 ), target.angles[2] );
|
||||
|
||||
self.lockOrientation = false;
|
||||
target.lockOrientation = false;
|
||||
|
||||
// Make sure we can move to the selected point ( no re-try for now )
|
||||
return Melee_UpdateAndValidateStartPos();
|
||||
}
|
||||
|
||||
riotshield_startMoveTransition()
|
||||
{
|
||||
if ( isdefined( self.disableExits ) )
|
||||
return;
|
||||
|
||||
self orientmode( "face angle", self.angles[1] );
|
||||
self animmode( "zonly_physics", false );
|
||||
|
||||
if ( self.a.pose == "crouch" )
|
||||
{
|
||||
if ( isdefined( self.sprint ) || isdefined( self.fastwalk ) )
|
||||
transAnim = %riotshield_crouch2stand;
|
||||
else
|
||||
transAnim = %riotshield_crouch2walk;
|
||||
|
||||
rate = randomfloatrange( 0.9, 1.1 );
|
||||
self setFlaggedAnimKnobAllRestart( "startmove", transAnim, %body, 1, .1, rate );
|
||||
self animscripts\shared::DoNoteTracks( "startmove" );
|
||||
self clearanim( %riotshield_crouch2walk, 0.5 );
|
||||
}
|
||||
|
||||
if ( isdefined( self.sprint ) || isdefined( self.fastwalk ) )
|
||||
{
|
||||
self allowedStances( "stand", "crouch" );
|
||||
self.a.pose = "stand";
|
||||
}
|
||||
|
||||
self orientmode( "face default" );
|
||||
self animMode( "normal", false );
|
||||
|
||||
self thread riotshield_bullet_hit_shield();
|
||||
}
|
||||
|
||||
riotshield_endMoveTransition()
|
||||
{
|
||||
if ( self.prevScript == "move" && self.a.pose == "crouch" )
|
||||
{
|
||||
self clearAnim( %root, .2 );
|
||||
|
||||
rate = randomfloatrange( 0.9, 1.1 );
|
||||
self animmode( "zonly_physics" );
|
||||
self setFlaggedAnimKnobAllRestart( "endmove", %riotshield_walk2crouch_8, %body, 1, .2, rate );
|
||||
self animscripts\shared::DoNoteTracks( "endmove" );
|
||||
self animMode( "normal" );
|
||||
}
|
||||
|
||||
self allowedStances( "crouch" );
|
||||
}
|
||||
|
||||
riotshield_startCombat()
|
||||
{
|
||||
//assertex( self.combatmode == "no_cover", "riotshield AI combat mode should be 'no_cover'" );
|
||||
riotshield_endMoveTransition();
|
||||
self.pushable = false;
|
||||
self thread riotshield_bullet_hit_shield();
|
||||
}
|
||||
|
||||
riotshield_bullet_hit_shield()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
while (1)
|
||||
{
|
||||
self waittill( "bullet_hitshield" );
|
||||
|
||||
time = gettime();
|
||||
if ( time - self.shieldBulletBlockTime > 500 )
|
||||
self.shieldBulletBlockCount = 0;
|
||||
else
|
||||
self.shieldBulletBlockCount++;
|
||||
|
||||
self.shieldBulletBlockTime = time;
|
||||
if ( self.shieldBulletBlockCount > self.shieldBulletBlockLimit )
|
||||
self doDamage( 1, ( 0, 0, 0 ) ); // do minimal damage to fall down
|
||||
|
||||
if ( cointoss() )
|
||||
reactAnim = %riotshield_reactA;
|
||||
else
|
||||
reactAnim = %riotshield_reactB;
|
||||
|
||||
self notify( "new_hit_react" );
|
||||
self setFlaggedAnimRestart( "hitreact", reactAnim, 1, 0.1, 1 );
|
||||
self thread riotshield_bullet_hit_shield_clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
riotshield_bullet_hit_shield_clear()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "new_hit_react" );
|
||||
|
||||
self waittillmatch( "hitreact", "end" );
|
||||
self clearanim( %riotshield_react, 0.1 );
|
||||
}
|
||||
|
||||
|
||||
riotshield_grenadeCower()
|
||||
{
|
||||
if ( self.a.pose == "stand" )
|
||||
{
|
||||
self clearanim( %root, .2 );
|
||||
self setFlaggedAnimKnobAllRestart( "trans", %riotshield_walk2crouch_8, %body, 1, .2, 1.2 );
|
||||
self animscripts\shared::DoNoteTracks( "trans" );
|
||||
}
|
||||
|
||||
if ( isdefined( self.grenade ) )
|
||||
{
|
||||
faceGrenade = true;
|
||||
dirToGrenade = self.grenade.origin - self.origin;
|
||||
|
||||
if ( isdefined( self.enemy ) )
|
||||
{
|
||||
dirToEnemy = self.enemy.origin - self.origin;
|
||||
if ( vectorDot( dirToGrenade, dirToEnemy ) < 0 )
|
||||
faceGrenade = false;
|
||||
}
|
||||
|
||||
if ( faceGrenade )
|
||||
{
|
||||
relYaw = AngleClamp180( self.angles[ 1 ] - vectorToYaw( dirToGrenade ) );
|
||||
|
||||
if ( !isdefined( self.turnThreshold ) )
|
||||
self.turnThreshold = 55;
|
||||
|
||||
while ( abs( relYaw ) > self.turnThreshold )
|
||||
{
|
||||
if ( !isdefined( self.a.array ) )
|
||||
animscripts\combat::setup_anim_array();
|
||||
|
||||
if ( !self animscripts\combat::TurnToFaceRelativeYaw( relYaw ) )
|
||||
break;
|
||||
|
||||
relYaw = AngleClamp180( self.angles[ 1 ] - vectorToYaw( dirToGrenade ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self setAnimKnobAll( %riotshield_crouch_aim_5, %body, 1, 0.2, 1 );
|
||||
self setFlaggedAnimKnobAllRestart( "grenadecower", %riotshield_crouch_idle_add, %add_idle, 1, 0.2, self.animplaybackrate );
|
||||
self animscripts\shared::DoNoteTracks( "grenadecower" );
|
||||
}
|
||||
|
||||
|
||||
riotshield_flashbang()
|
||||
{
|
||||
self notify( "flashed" );
|
||||
|
||||
if ( !isdefined( self.a.onback ) )
|
||||
{
|
||||
rate = randomfloatrange( 0.9, 1.1 );
|
||||
self.frontShieldAngleCos = 1;
|
||||
|
||||
flashArray = [];
|
||||
flashArray[0] = %riotshield_crouch_grenade_flash1;
|
||||
flashArray[1] = %riotshield_crouch_grenade_flash2;
|
||||
flashArray[2] = %riotshield_crouch_grenade_flash3;
|
||||
flashArray[3] = %riotshield_crouch_grenade_flash4;
|
||||
flashAnim = flashArray[ randomint( flashArray.size ) ];
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "flashanim", flashAnim, %body, 1, .1, rate );
|
||||
self.minPainDamage = 1000;
|
||||
}
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "flashanim" );
|
||||
self.minPainDamage = 0;
|
||||
self.frontShieldAngleCos = 0.5;
|
||||
}
|
||||
|
||||
|
||||
riotshield_pain()
|
||||
{
|
||||
// all the pain animations are in crouch
|
||||
self.a.pose = "crouch";
|
||||
|
||||
if ( usingSideArm() )
|
||||
forceUseWeapon( self.primaryweapon, "primary" );
|
||||
|
||||
if ( !isdefined( self.a.onback ) )
|
||||
{
|
||||
rate = randomfloatrange( 0.8, 1.15 );
|
||||
self.frontShieldAngleCos = 1;
|
||||
if ( ( self.damageYaw < -120 || self.damageYaw > 120 ) && isExplosiveDamageMOD( self.damageMOD ) )
|
||||
{
|
||||
painArray = [];
|
||||
painArray[0] = %riotshield_crouch_grenade_blowback;
|
||||
painArray[1] = %riotshield_crouch_grenade_blowbackL;
|
||||
painArray[2] = %riotshield_crouch_grenade_blowbackR;
|
||||
painAnim = painArray[ randomint( painArray.size ) ];
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "painanim", painAnim, %body, 1, .2, rate );
|
||||
self.minPainDamage = 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
self setFlaggedAnimKnobAllRestart( "painanim", %riotshield_crouch_pain, %body, 1, .2, rate );
|
||||
}
|
||||
}
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "painanim" );
|
||||
self.minPainDamage = 0;
|
||||
self.frontShieldAngleCos = 0.5;
|
||||
}
|
||||
|
||||
riotshield_death()
|
||||
{
|
||||
if ( isdefined( self.a.onback ) && self.a.pose == "crouch" )
|
||||
{
|
||||
deathArray = [];
|
||||
deathArray[0] = %dying_back_death_v2;
|
||||
deathArray[1] = %dying_back_death_v3;
|
||||
deathArray[2] = %dying_back_death_v4;
|
||||
deathAnim = deathArray[ randomint( deathArray.size ) ];
|
||||
|
||||
self animscripts\death::playDeathAnim( deathAnim );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( self.prevScript == "pain" || self.prevScript == "flashed" )
|
||||
doShieldDeath = randomInt( 2 ) == 0;
|
||||
else
|
||||
doShieldDeath = true;
|
||||
|
||||
if ( doShieldDeath )
|
||||
{
|
||||
if ( cointoss() )
|
||||
deathAnim = %riotshield_crouch_death;
|
||||
else
|
||||
deathAnim = %riotshield_crouch_death_fallback;
|
||||
|
||||
self animscripts\death::playDeathAnim( deathAnim );
|
||||
return true;
|
||||
}
|
||||
|
||||
self.a.pose = "crouch";
|
||||
return false;
|
||||
}
|
||||
|
||||
init_riotshield_animsets()
|
||||
{
|
||||
// move animations
|
||||
animset = [];
|
||||
animset[ "sprint" ] = %riotshield_sprint;
|
||||
animset[ "prone" ] = %prone_crawl;
|
||||
|
||||
animset[ "straight" ] = %riotshield_run_F;
|
||||
animset[ "straight_variation" ] = %riotshield_run_F;
|
||||
|
||||
animset[ "move_f" ] = %riotshield_run_F;
|
||||
animset[ "move_l" ] = %riotshield_run_L;
|
||||
animset[ "move_r" ] = %riotshield_run_R;
|
||||
animset[ "move_b" ] = %riotshield_run_B;
|
||||
|
||||
animset[ "crouch" ] = %riotshield_crouchwalk_F;
|
||||
animset[ "crouch_l" ] = %riotshield_crouchwalk_L;
|
||||
animset[ "crouch_r" ] = %riotshield_crouchwalk_R;
|
||||
animset[ "crouch_b" ] = %riotshield_crouchwalk_B;
|
||||
|
||||
animset[ "stairs_up" ] = %traverse_stair_run_01;
|
||||
animset[ "stairs_down" ] = %traverse_stair_run_down;
|
||||
|
||||
self.customMoveAnimSet[ "run" ] = animset;
|
||||
self.customMoveAnimSet[ "walk" ] = animset;
|
||||
self.customMoveAnimSet[ "cqb" ] = animset;
|
||||
|
||||
self.customIdleAnimSet = [];
|
||||
self.customIdleAnimSet[ "crouch" ] = %riotshield_crouch_aim_5;
|
||||
self.customIdleAnimSet[ "crouch_add" ] = %riotshield_crouch_idle_add;
|
||||
self.customIdleAnimSet[ "stand" ] = %riotshield_crouch_aim_5;
|
||||
self.customIdleAnimSet[ "stand_add" ] = %riotshield_crouch_idle_add;
|
||||
|
||||
self.a.pose = "crouch";
|
||||
self allowedStances( "crouch" );
|
||||
|
||||
// combat animations
|
||||
animset = anim.animsets.defaultStand;
|
||||
|
||||
animset[ "add_aim_up" ] = %riotshield_crouch_aim_8;
|
||||
animset[ "add_aim_down" ] = %riotshield_crouch_aim_2;
|
||||
animset[ "add_aim_left" ] = %riotshield_crouch_aim_4;
|
||||
animset[ "add_aim_right" ] = %riotshield_crouch_aim_6;
|
||||
|
||||
animset[ "straight_level" ] = %riotshield_crouch_aim_5;
|
||||
|
||||
animset[ "fire" ] = %riotshield_crouch_fire_auto;
|
||||
animset[ "single" ] = array( %riotshield_crouch_fire_single );
|
||||
|
||||
// remove this burst, semi nonsense soon
|
||||
animset[ "burst2" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "burst3" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "burst4" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "burst5" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "burst6" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "semi2" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "semi3" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "semi4" ] = %riotshield_crouch_fire_burst;
|
||||
animset[ "semi5" ] = %riotshield_crouch_fire_burst;
|
||||
|
||||
animset[ "exposed_idle" ] = array( %riotshield_crouch_idle_add, %riotshield_crouch_twitch );
|
||||
animset[ "exposed_grenade" ] = array( %riotshield_crouch_grenade_toss );
|
||||
|
||||
animset[ "reload" ] = array( %riotshield_crouch_reload );
|
||||
animset[ "reload_crouchhide" ] = array( %riotshield_crouch_reload );
|
||||
|
||||
animset[ "turn_left_45" ] = %riotshield_crouch_Lturn;
|
||||
animset[ "turn_left_90" ] = %riotshield_crouch_Lturn;
|
||||
animset[ "turn_left_135" ] = %riotshield_crouch_Lturn;
|
||||
animset[ "turn_left_180" ] = %riotshield_crouch_Lturn;
|
||||
animset[ "turn_right_45" ] = %riotshield_crouch_Rturn;
|
||||
animset[ "turn_right_90" ] = %riotshield_crouch_Rturn;
|
||||
animset[ "turn_right_135" ] = %riotshield_crouch_Rturn;
|
||||
animset[ "turn_right_180" ] = %riotshield_crouch_Rturn;
|
||||
|
||||
animset[ "stand_2_crouch" ] = %riotshield_walk2crouch_8;
|
||||
|
||||
self animscripts\init_common::set_animset_complete_custom_stand( animset );
|
||||
self animscripts\init_common::set_animset_complete_custom_crouch( animset );
|
||||
|
||||
self.choosePoseFunc = ::riotshield_choose_pose;
|
||||
self.painFunction = ::riotshield_pain;
|
||||
self.specialDeathFunc = ::riotshield_death;
|
||||
self.specialFlashedFunc = ::riotshield_flashbang;
|
||||
self.grenadeCowerFunction = ::riotshield_grenadeCower;
|
||||
self.customMoveTransition = ::riotshield_startMoveTransition;
|
||||
self.permanentCustomMoveTransition = true;
|
||||
|
||||
set_exception( "exposed", ::riotshield_startCombat );
|
||||
//set_exception( "stop_immediate", ::riotshield_endMoveTransition );
|
||||
}
|
||||
|
||||
riotshield_choose_pose( preferredPose )
|
||||
{
|
||||
if ( isdefined( self.grenade ) )
|
||||
return "stand";
|
||||
|
||||
return self animscripts\utility::choosePose( preferredPose );
|
||||
}
|
||||
|
||||
|
||||
riotshield_sprint_on()
|
||||
{
|
||||
self.maxFaceEnemyDist = 128;
|
||||
self.sprint = true;
|
||||
self orientmode( "face default" );
|
||||
self.lockorientation = false;
|
||||
|
||||
self.walkDist = 32;
|
||||
self.walkDistFacingMotion = 32;
|
||||
}
|
||||
|
||||
riotshield_fastwalk_on()
|
||||
{
|
||||
self.maxFaceEnemyDist = 128;
|
||||
self.fastwalk = true;
|
||||
|
||||
self.walkDist = 32;
|
||||
self.walkDistFacingMotion = 32;
|
||||
}
|
||||
|
||||
|
||||
riotshield_sprint_off()
|
||||
{
|
||||
self.maxFaceEnemyDist = RIOTSHIELD_FACE_ENEMY_DIST;
|
||||
|
||||
self.walkDist = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
self.walkDistFacingMotion = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
self.sprint = undefined;
|
||||
self allowedStances( "crouch" );
|
||||
}
|
||||
|
||||
riotshield_fastwalk_off()
|
||||
{
|
||||
self.maxFaceEnemyDist = RIOTSHIELD_FACE_ENEMY_DIST;
|
||||
|
||||
self.walkDist = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
self.walkDistFacingMotion = RIOTSHIELD_FORCE_WALK_DIST;
|
||||
self.fastwalk = undefined;
|
||||
self allowedStances( "crouch" );
|
||||
}
|
||||
|
||||
null_func()
|
||||
{
|
||||
}
|
||||
|
||||
riotshield_init_flee()
|
||||
{
|
||||
// hack to restart move script
|
||||
if ( self.script == "move" )
|
||||
self animcustom( ::null_func );
|
||||
|
||||
self.customMoveTransition = ::riotshield_flee_and_drop_shield;
|
||||
}
|
||||
|
||||
riotshield_flee_and_drop_shield()
|
||||
{
|
||||
// restore this incase flee gets interrupted
|
||||
self.customMoveTransition = ::riotshield_startMoveTransition;
|
||||
|
||||
self animmode( "zonly_physics", false );
|
||||
self orientmode( "face current" );
|
||||
|
||||
if ( !isdefined( self.dropShieldInPlace ) && isdefined( self.enemy ) && vectordot( self.lookaheadDir, anglesToForward( self.angles ) ) < 0 )
|
||||
fleeAnim = %riotshield_crouch2walk_2flee;
|
||||
else
|
||||
fleeAnim = %riotshield_crouch2stand_shield_drop;
|
||||
|
||||
rate = randomFloatRange( 0.85, 1.1 );
|
||||
self SetFlaggedAnimKnobAll( "fleeanim", fleeAnim, %root, 1, .1, rate );
|
||||
self animscripts\shared::DoNoteTracks( "fleeanim" ); // return on code_move
|
||||
|
||||
self.maxFaceEnemyDist = 32;
|
||||
self.lockOrientation = false;
|
||||
self orientmode( "face default" );
|
||||
self animmode( "normal", false );
|
||||
self animscripts\shared::DoNoteTracks( "fleeanim" );
|
||||
self clearanim( fleeAnim, 0.2 );
|
||||
self.maxFaceEnemyDist = 128;
|
||||
}
|
||||
|
||||
riotshield_turn_into_regular_ai()
|
||||
{
|
||||
self.subclass = "regular";
|
||||
|
||||
self.combatMode = "cover";
|
||||
|
||||
self.approachTypeFunc = undefined;
|
||||
self.approachConditionCheckFunc = undefined;
|
||||
self.faceEnemyArrival = undefined;
|
||||
self.disableCoverArrivalsOnly = undefined;
|
||||
self.pathRandomPercent = 0;
|
||||
self.interval = 80;
|
||||
self.disableDoorBehavior = undefined;
|
||||
self.no_pistol_switch = undefined;
|
||||
self.dontShootWhileMoving = undefined;
|
||||
self.disableBulletWhizbyReaction = undefined;
|
||||
self.disableFriendlyFireReaction = undefined;
|
||||
self.neverSprintForVariation = undefined;
|
||||
self.maxFaceEnemyDist = 128;
|
||||
self.noMeleeChargeDelay = undefined;
|
||||
self.meleeChargeDistSq = undefined;
|
||||
self.meleePlayerWhileMoving = undefined;
|
||||
self.useMuzzleSideOffset = undefined;
|
||||
|
||||
self.pathEnemyFightDist = 128;
|
||||
self.pathenemylookahead = 128;
|
||||
|
||||
self.walkDist = 256;
|
||||
self.walkDistFacingMotion = 64;
|
||||
self.lockorientation = false;
|
||||
|
||||
self.frontShieldAngleCos = 1;
|
||||
self.noGrenadeReturnThrow = false;
|
||||
|
||||
self.ignoresuppression = false;
|
||||
self.sprint = undefined;
|
||||
|
||||
self allowedStances( "stand", "crouch", "prone" );
|
||||
|
||||
self.specialMelee_Standard = undefined;
|
||||
self.specialMeleeChooseAction = undefined;
|
||||
|
||||
self enable_turnAnims();
|
||||
|
||||
self.bullet_resistance = undefined;
|
||||
self remove_damage_function( maps\_spawner::bullet_resistance );
|
||||
self remove_damage_function( animscripts\pain::additive_pain );
|
||||
|
||||
self animscripts\init_common::clear_custom_animset();
|
||||
|
||||
self.choosePoseFunc = animscripts\utility::choosePose;
|
||||
self.painFunction = undefined;
|
||||
self.specialDeathFunc = undefined;
|
||||
self.specialFlashedFunc = undefined;
|
||||
self.grenadeCowerFunction = undefined;
|
||||
self.customMoveTransition = undefined;
|
||||
self.permanentCustomMoveTransition = undefined;
|
||||
|
||||
clear_exception( "exposed" );
|
||||
clear_exception( "stop_immediate" );
|
||||
}
|
1177
animscripts/run.gsc
Normal file
1177
animscripts/run.gsc
Normal file
File diff suppressed because it is too large
Load Diff
326
animscripts/saw/common.gsc
Normal file
326
animscripts/saw/common.gsc
Normal file
@ -0,0 +1,326 @@
|
||||
main( turret )
|
||||
{
|
||||
self endon( "killanimscript" );// code
|
||||
|
||||
assert( isdefined( turret ) );
|
||||
|
||||
animscripts\utility::initialize( "saw" );
|
||||
|
||||
// when we ran our postscriptfunc we may have decided to stop using our turret,
|
||||
// in which case it's gone now
|
||||
if ( !isdefined( turret ) )
|
||||
return;
|
||||
|
||||
self.a.special = "saw";
|
||||
|
||||
pauseUntilTime = getTime();
|
||||
turretState = "start";
|
||||
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "none" );
|
||||
turret show();
|
||||
|
||||
if ( isDefined( turret.aiOwner ) )
|
||||
{
|
||||
assert( turret.aiOwner == self );
|
||||
self.a.postScriptFunc = ::postScriptFunc;
|
||||
self.a.usingTurret = turret;
|
||||
turret notify( "being_used" );
|
||||
self thread stopUsingTurretWhenNodeLost();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.postScriptFunc = ::preplacedPostScriptFunc;
|
||||
}
|
||||
|
||||
turret.doFiring = false;
|
||||
self thread fireController( turret );
|
||||
|
||||
|
||||
self setTurretAnim( self.primaryTurretAnim );
|
||||
self setAnimKnobRestart( self.primaryTurretAnim, 1, 0.2, 1 );
|
||||
|
||||
self setAnimKnobLimitedRestart( self.additiveTurretIdle );
|
||||
self setAnimKnobLimitedRestart( self.additiveTurretFire );
|
||||
|
||||
turret setAnimKnobLimitedRestart( turret.additiveTurretIdle );
|
||||
turret setAnimKnobLimitedRestart( turret.additiveTurretFire );
|
||||
|
||||
turret endon( "death" );
|
||||
for ( ;; )
|
||||
{
|
||||
// tagBK< NOTE > System allows for dynamic updates of fire rate. Ported from above.
|
||||
if ( isDefined( turret.script_delay_min ))
|
||||
{
|
||||
turret_delay = turret.script_delay_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
turret_delay = maps\_mgturret::burst_fire_settings( "delay" );
|
||||
}
|
||||
|
||||
if ( isDefined( turret.script_delay_max ))
|
||||
{
|
||||
turret_delay_range = turret.script_delay_max - turret_delay;
|
||||
}
|
||||
else
|
||||
{
|
||||
turret_delay_range = maps\_mgturret::burst_fire_settings( "delay_range" );
|
||||
}
|
||||
|
||||
if ( isDefined( turret.script_burst_min ))
|
||||
{
|
||||
turret_burst = turret.script_burst_min;
|
||||
}
|
||||
else
|
||||
{
|
||||
turret_burst = maps\_mgturret::burst_fire_settings( "burst" );
|
||||
}
|
||||
|
||||
if ( isDefined( turret.script_burst_max ))
|
||||
{
|
||||
turret_burst_range = turret.script_burst_max - turret_burst;
|
||||
}
|
||||
else
|
||||
{
|
||||
turret_burst_range = maps\_mgturret::burst_fire_settings( "burst_range" );
|
||||
}
|
||||
|
||||
// Recalculate wait time.
|
||||
if ( turret_burst_range <= 0 )
|
||||
{
|
||||
waittime = turret_delay;
|
||||
burst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
waittime = randomFloatRange( turret_burst, turret_burst + turret_burst_range );
|
||||
burst = true;
|
||||
}
|
||||
|
||||
// Primary update.
|
||||
if ( turret.doFiring )
|
||||
{
|
||||
thread DoShoot( turret );
|
||||
|
||||
if ( burst == false )
|
||||
{
|
||||
turret notify( "turretstatechange" );
|
||||
}
|
||||
|
||||
self waitTimeOrUntilTurretStateChange( waittime, turret );
|
||||
turret notify( "turretstatechange" );
|
||||
|
||||
if ( turret.doFiring )
|
||||
{
|
||||
thread DoAim( turret );
|
||||
wait( waittime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
thread DoAim( turret );
|
||||
turret waittill( "turretstatechange" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitTimeOrUntilTurretStateChange( time, turret )
|
||||
{
|
||||
turret endon( "turretstatechange" );
|
||||
wait time;
|
||||
}
|
||||
|
||||
fireController( turret )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
fovdot = cos( 15 );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
while ( isDefined( self.enemy ) )
|
||||
{
|
||||
enemypos = self.enemy.origin;
|
||||
|
||||
//if ( isSentient( enemypos ) )
|
||||
// enemypos += (0,0,32);
|
||||
turretAimPos = turret getTagAngles( "tag_aim" );
|
||||
|
||||
if ( within_fov( turret.origin, turretAimPos, enemypos, fovdot ) || distanceSquared( turret.origin, enemyPos ) < 200 * 200 )
|
||||
{
|
||||
if ( !turret.doFiring )
|
||||
{
|
||||
turret.doFiring = true;
|
||||
turret notify( "turretstatechange" );
|
||||
}
|
||||
}
|
||||
else if ( turret.doFiring )
|
||||
{
|
||||
turret.doFiring = false;
|
||||
turret notify( "turretstatechange" );
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
if ( turret.doFiring )
|
||||
{
|
||||
turret.doFiring = false;
|
||||
turret notify( "turretstatechange" );
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
turretTimer( duration, turret )
|
||||
{
|
||||
if ( duration <= 0 )
|
||||
return;
|
||||
|
||||
self endon( "killanimscript" );// code
|
||||
turret endon( "turretstatechange" );// code
|
||||
|
||||
wait( duration );
|
||||
turret notify( "turretstatechange" );
|
||||
}
|
||||
|
||||
stopUsingTurretWhenNodeLost()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
// sometimes someone else will come and steal our node. when that happens,
|
||||
// we should leave so we don't try to use the same MG at once.
|
||||
while ( 1 )
|
||||
{
|
||||
if ( !isdefined( self.node ) || distancesquared( self.origin, self.node.origin ) > 64 * 64 )
|
||||
self stopUseTurret();
|
||||
wait .25;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
postScriptFunc( animscript )
|
||||
{
|
||||
if ( animscript == "pain" )
|
||||
{
|
||||
if ( isdefined( self.node ) && distancesquared( self.origin, self.node.origin ) < 64 * 64 )
|
||||
{
|
||||
self.a.usingTurret hide();
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
self.a.postScriptFunc = ::postPainFunc;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
self stopUseTurret();
|
||||
}
|
||||
}
|
||||
|
||||
assert( self.a.usingTurret.aiOwner == self );
|
||||
|
||||
if ( animscript == "saw" )
|
||||
{
|
||||
turret = self getTurret();
|
||||
assert( isDefined( turret ) && turret == self.a.usingTurret );
|
||||
return;
|
||||
}
|
||||
|
||||
self.a.usingTurret delete();
|
||||
self.a.usingTurret = undefined;
|
||||
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
|
||||
postPainFunc( animscript )
|
||||
{
|
||||
assert( isDefined( self.a.usingTurret ) );
|
||||
assert( self.a.usingTurret.aiOwner == self );
|
||||
|
||||
if ( !isdefined( self.node ) || distancesquared( self.origin, self.node.origin ) > 64 * 64 )
|
||||
{
|
||||
self stopUseTurret();
|
||||
|
||||
self.a.usingTurret delete();
|
||||
self.a.usingTurret = undefined;
|
||||
|
||||
// we may have gone into long death, in which case our weapon is gone
|
||||
if ( isdefined( self.weapon ) && self.weapon != "none" )
|
||||
{
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
}
|
||||
else if ( animscript != "saw" )
|
||||
{
|
||||
self.a.usingTurret delete();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
preplacedPostScriptFunc( animscript )
|
||||
{
|
||||
self animscripts\shared::placeWeaponOn( self.weapon, "right" );
|
||||
}
|
||||
|
||||
|
||||
within_fov( start_origin, start_angles, end_origin, fov )
|
||||
{
|
||||
normal = vectorNormalize( end_origin - start_origin );
|
||||
forward = anglestoforward( start_angles );
|
||||
dot = vectorDot( forward, normal );
|
||||
|
||||
return dot >= fov;
|
||||
}
|
||||
|
||||
|
||||
// ==================================
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
DoShoot( turret )
|
||||
{
|
||||
self setAnim( %additive_saw_idle, 0, .1 );
|
||||
self setAnim( %additive_saw_fire, 1, .1 );
|
||||
|
||||
turret turretDoShootAnims();
|
||||
|
||||
TurretDoShoot( turret );
|
||||
}
|
||||
|
||||
DoAim( turret )
|
||||
{
|
||||
self setAnim( %additive_saw_idle, 1, .1 );
|
||||
self setAnim( %additive_saw_fire, 0, .1 );
|
||||
|
||||
turret turretDoAimAnims();
|
||||
}
|
||||
|
||||
|
||||
//=====================================
|
||||
#using_animtree( "mg42" );
|
||||
|
||||
TurretDoShoot( turret )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
turret endon( "turretstatechange" );// code or script
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
turret ShootTurret();
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
turretDoShootAnims()
|
||||
{
|
||||
self setAnim( %additive_saw_idle, 0, .1 );
|
||||
self setAnim( %additive_saw_fire, 1, .1 );
|
||||
}
|
||||
|
||||
turretDoAimAnims()
|
||||
{
|
||||
self setAnim( %additive_saw_idle, 1, .1 );
|
||||
self setAnim( %additive_saw_fire, 0, .1 );
|
||||
}
|
||||
|
36
animscripts/saw/crouch.gsc
Normal file
36
animscripts/saw/crouch.gsc
Normal file
@ -0,0 +1,36 @@
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// It'd be nice if I had an animation to get to stand without moving...
|
||||
self.a.movement = "stop";
|
||||
|
||||
turret = self getTurret();
|
||||
turret thread turretInit( self );
|
||||
|
||||
self.primaryTurretAnim = %crouchSAWgunner_aim;
|
||||
self.additiveTurretIdle = %saw_gunner_lowwall_idle;
|
||||
self.additiveTurretFire = %saw_gunner_lowwall_firing;
|
||||
|
||||
thread animscripts\saw\common::main( turret );
|
||||
}
|
||||
|
||||
//=====================================
|
||||
#using_animtree( "mg42" );
|
||||
|
||||
turretInit( owner )
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
|
||||
self.additiveTurretIdle = %saw_gunner_lowwall_idle_mg;
|
||||
self.additiveTurretFire = %saw_gunner_lowwall_firing_mg;
|
||||
|
||||
self endon( "death" );
|
||||
owner waittill( "killanimscript" );// code
|
||||
|
||||
self stopUseAnimTree();
|
||||
}
|
37
animscripts/saw/prone.gsc
Normal file
37
animscripts/saw/prone.gsc
Normal file
@ -0,0 +1,37 @@
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "prone";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// It'd be nice if I had an animation to get to stand without moving...
|
||||
self.a.movement = "stop";
|
||||
|
||||
turret = self getTurret();
|
||||
turret thread turretInit( self );
|
||||
|
||||
self.primaryTurretAnim = %proneSAWgunner_aim;
|
||||
self.additiveTurretIdle = %saw_gunner_prone_idle;
|
||||
self.additiveTurretFire = %saw_gunner_prone_firing;
|
||||
|
||||
thread animscripts\saw\common::main( turret );
|
||||
}
|
||||
|
||||
//=====================================
|
||||
#using_animtree( "mg42" );
|
||||
|
||||
turretInit( owner )
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
|
||||
self.additiveTurretIdle = %saw_gunner_prone_idle_mg;
|
||||
self.additiveTurretFire = %saw_gunner_prone_firing_mg;
|
||||
|
||||
self endon( "death" );
|
||||
owner waittill( "killanimscript" );// code
|
||||
|
||||
self stopUseAnimTree();
|
||||
}
|
||||
|
37
animscripts/saw/stand.gsc
Normal file
37
animscripts/saw/stand.gsc
Normal file
@ -0,0 +1,37 @@
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// It'd be nice if I had an animation to get to stand without moving...
|
||||
self.a.movement = "stop";
|
||||
|
||||
turret = self getTurret();
|
||||
turret thread turretInit( self );
|
||||
|
||||
self.primaryTurretAnim = %standSAWgunner_aim;
|
||||
self.additiveTurretIdle = %saw_gunner_idle;
|
||||
self.additiveTurretFire = %saw_gunner_firing_add;
|
||||
|
||||
thread animscripts\saw\common::main( turret );
|
||||
}
|
||||
|
||||
//=====================================
|
||||
#using_animtree( "mg42" );
|
||||
|
||||
turretInit( owner )
|
||||
{
|
||||
self UseAnimTree( #animtree );
|
||||
|
||||
self.additiveTurretIdle = %saw_gunner_idle_mg;
|
||||
self.additiveTurretFire = %saw_gunner_firing_mg_add;
|
||||
|
||||
self endon( "death" );
|
||||
owner waittill( "killanimscript" );// code
|
||||
|
||||
self stopUseAnimTree();
|
||||
}
|
||||
|
70
animscripts/scripted.gsc
Normal file
70
animscripts/scripted.gsc
Normal file
@ -0,0 +1,70 @@
|
||||
// Note that this script is called from the level script command animscripted, only for AI. If animscripted
|
||||
// is done on a script model, this script is not called - startscriptedanim is called directly.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
main()
|
||||
{
|
||||
//thread [[anim.println]]("Entering animscripts\\scripted. anim: ",self.codeScripted["anim"],", notify: ",self.codeScripted["notifyName"],", dialogue: ",self.scripted_dialogue,", facial: ",self.facial_animation, "root: ", self.codeScripted["root"]);#/
|
||||
self endon( "death" );
|
||||
|
||||
// wait (0);
|
||||
self notify( "killanimscript" );
|
||||
self notify( "clearSuppressionAttack" );
|
||||
self.a.suppressingEnemy = false;
|
||||
|
||||
|
||||
self.codeScripted[ "root" ] = %body; // TEMP!
|
||||
|
||||
self endon( "end_sequence" );
|
||||
// Causes potential variable overflow in Stalingrad
|
||||
// self thread DebugPrintEndSequence();
|
||||
self startscriptedanim( self.codeScripted[ "notifyName" ], self.codeScripted[ "origin" ], self.codeScripted[ "angles" ], self.codeScripted[ "anim" ], self.codeScripted[ "blend_time" ], self.codeScripted[ "animMode" ], self.codeScripted[ "root" ] );
|
||||
|
||||
self.codeScripted = undefined;
|
||||
// if (isdefined (self.facial_animation))
|
||||
// {
|
||||
// self SetFlaggedAnimRestart("scripted_anim_facedone", self.facial_animation, 1, .1, 1);
|
||||
// self.facial_animation = undefined;
|
||||
// }
|
||||
if ( isdefined( self.scripted_dialogue ) || isdefined( self.facial_animation ) )
|
||||
{
|
||||
self animscripts\face::SaySpecificDialogue( self.facial_animation, self.scripted_dialogue, 0.9, "scripted_anim_facedone" );
|
||||
self.facial_animation = undefined;
|
||||
self.scripted_dialogue = undefined;
|
||||
}
|
||||
|
||||
if ( isdefined( self.deathstring_passed ) )
|
||||
self.deathstring = self.deathstring_passed;
|
||||
|
||||
self waittill( "killanimscript" );
|
||||
}
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
init( notifyName, origin, angles, theAnim, blend_time, animMode, root )
|
||||
{
|
||||
self.codeScripted[ "notifyName" ] = notifyName;
|
||||
self.codeScripted[ "origin" ] = origin;
|
||||
self.codeScripted[ "angles" ] = angles;
|
||||
self.codeScripted[ "anim" ] = theAnim;
|
||||
self.codeScripted[ "blend_time" ] = blend_time;
|
||||
|
||||
if ( isDefined( animMode ) )
|
||||
self.codeScripted[ "animMode" ] = animMode;
|
||||
else
|
||||
self.codeScripted[ "animMode" ] = "normal";
|
||||
if ( isDefined( root ) )
|
||||
self.codeScripted[ "root" ] = root;
|
||||
else
|
||||
self.codeScripted[ "root" ] = %body;
|
||||
}
|
||||
|
||||
// Causes potential variable overflow in Stalingrad
|
||||
|
||||
/*
|
||||
DebugPrintEndSequence()
|
||||
{
|
||||
self endon ("death");
|
||||
self waittill ("end_sequence");
|
||||
/#thread [[anim.println]]("scripted.gsc: \"end_sequence\" was notified. Time: ",GetTime(),".");#/
|
||||
}
|
||||
*/
|
193
animscripts/scripted/truckride_backoftruck.gsc
Normal file
193
animscripts/scripted/truckride_backoftruck.gsc
Normal file
@ -0,0 +1,193 @@
|
||||
#include animscripts\SetPoseMovement;
|
||||
#include animscripts\combat_utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
hackangle()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
enemyAngle = animscripts\utility::GetYawToEnemy();
|
||||
self OrientMode( "face angle", enemyAngle );
|
||||
wait .05;
|
||||
}
|
||||
}
|
||||
|
||||
main()
|
||||
{
|
||||
println( "anim1" );
|
||||
self endon( "killanimscript" );
|
||||
self endon( "outoftruck" );
|
||||
animscripts\utility::initialize( "l33t truckride combat" );
|
||||
|
||||
thread hackangle();
|
||||
self OrientMode( "face enemy" );
|
||||
if ( randomint( 100 ) > 50 )
|
||||
nextaction = ( "stand" );
|
||||
else
|
||||
nextaction = ( "crouch" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
// Nothing below will work if our gun is completely empty.
|
||||
|
||||
Reload( 0 );
|
||||
// if ( canShootstand && canStand &&
|
||||
// ( !canShootCrouch || !canCrouch || ( dist < anim.standRangeSq )) )
|
||||
|
||||
if ( nextaction == ( "stand" ) )
|
||||
{
|
||||
timer = gettime() + randomint( 2000 ) + 2000;
|
||||
while ( timer > gettime() )
|
||||
{
|
||||
|
||||
|
||||
// self animscripts\aim::aim();
|
||||
success = LocalShootVolley( 0 );
|
||||
// if (!success)
|
||||
// self interruptPoint(); // We couldn't shoot for some reason, so now would be a good time to run for cover.
|
||||
nextaction = ( "crouch" );
|
||||
|
||||
}
|
||||
}
|
||||
else if ( nextaction == ( "crouch" ) )
|
||||
{
|
||||
timer = gettime() + randomint( 2000 ) + 2000;
|
||||
while ( timer > gettime() )
|
||||
{
|
||||
/#thread [[ anim.println ]]( "ExposedCombat - Crouched combat" );#/
|
||||
|
||||
|
||||
// self animscripts\aim::aim();
|
||||
success = ShootVolley();
|
||||
if ( !success )
|
||||
continue;
|
||||
nextaction = ( "stand" );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LocalShootVolley( completeLastShot, forceShoot, posOverrideEntity )
|
||||
{
|
||||
if ( !isDefined( forceShoot ) )
|
||||
{
|
||||
forceShoot = "dontForceShoot";
|
||||
}
|
||||
self animscripts\shared::placeWeaponOn( self.primaryweapon, "none" );
|
||||
if ( self.a.pose == "stand" )
|
||||
{
|
||||
anim_autofire = %stand_shoot_auto;
|
||||
anim_semiautofire = %stand_shoot;
|
||||
anim_boltfire = %stand_shoot;
|
||||
}
|
||||
else// assume crouch
|
||||
{
|
||||
anim_autofire = %crouch_shoot_auto;
|
||||
anim_semiautofire = %crouch_shoot;
|
||||
anim_boltfire = %crouch_shoot;
|
||||
}
|
||||
|
||||
if ( animscripts\weaponList::usingAutomaticWeapon() )
|
||||
{
|
||||
self animscripts\face::SetIdleFace( anim.autofireface );
|
||||
self setflaggedanimknob( "animdone", anim_autofire, 1, .15, 0 );
|
||||
wait 0.20;
|
||||
animRate = animscripts\weaponList::autoShootAnimRate();
|
||||
self setFlaggedAnimKnobRestart( "shootdone", anim_autofire, 1, .05, animRate );
|
||||
numShots = randomint( 8 ) + 6;
|
||||
enemyAngle = animscripts\utility::AbsYawToEnemy();
|
||||
/#thread [[ anim.locspam ]]( "c16a" );#/
|
||||
for ( i = 0;( i < numShots && self.bulletsInClip > 0 && enemyAngle < 20 ); i++ )
|
||||
{
|
||||
self waittillmatch( "shootdone", "fire" );
|
||||
if ( isDefined( posOverrideEntity ) )
|
||||
{
|
||||
if ( isSentient( posOverrideEntity ) )
|
||||
{
|
||||
pos = posOverrideEntity GetEye();
|
||||
}
|
||||
else
|
||||
{
|
||||
pos = posOverrideEntity.origin;
|
||||
}
|
||||
self shoot( 1, pos );
|
||||
}
|
||||
else
|
||||
self shoot();
|
||||
self decrementBulletsInClip();
|
||||
enemyAngle = animscripts\utility::AbsYawToEnemy();
|
||||
}
|
||||
if ( completeLastShot )
|
||||
wait animscripts\weaponList::waitAfterShot();
|
||||
self notify( "stopautofireFace" );
|
||||
}
|
||||
else if ( animscripts\weaponList::usingSemiAutoWeapon() )
|
||||
{
|
||||
|
||||
self animscripts\face::SetIdleFace( anim.aimface );
|
||||
|
||||
self setanimknob( anim_semiautofire, 1, .15, 0 );
|
||||
wait 0.2;
|
||||
|
||||
rand = randomint( 2 ) + 2;
|
||||
for ( i = 0;( i < rand && self.bulletsInClip > 0 ); i++ )
|
||||
{
|
||||
self setFlaggedAnimKnobRestart( "shootdone", anim_semiautofire, 1, 0, 1 );
|
||||
if ( isDefined( posOverrideEntity ) )
|
||||
self shoot( 1, posOverrideEntity . origin );
|
||||
else
|
||||
self shoot();
|
||||
self decrementBulletsInClip();
|
||||
/#thread [[ anim.locspam ]]( "c17.1b" );#/
|
||||
shootTime = animscripts\weaponList::shootAnimTime();
|
||||
quickTime = animscripts\weaponList::waitAfterShot();
|
||||
wait quickTime;
|
||||
if ( ( ( completeLastShot ) || ( i < rand - 1 ) ) && shootTime > quickTime )
|
||||
wait shootTime - quickTime;
|
||||
}
|
||||
}
|
||||
else// Bolt action
|
||||
{
|
||||
Rechamber(); // In theory you will almost never need to rechamber here, because you will have done
|
||||
// it somewhere smarter, like in cover.
|
||||
self animscripts\face::SetIdleFace( anim.aimface );
|
||||
// Slowly blend in the first frame of the shoot instead of playing the transition.
|
||||
self setanimknob( anim_boltfire, 1, .15, 0 );
|
||||
|
||||
wait 0.2;
|
||||
|
||||
self setFlaggedAnimKnobRestart( "shootdone", anim_boltfire, 1, 0, 1 );
|
||||
if ( isDefined( posOverrideEntity ) )
|
||||
self shoot( 1, posOverrideEntity . origin );
|
||||
else
|
||||
self shoot();
|
||||
self.a.needsToRechamber = 1;
|
||||
self decrementBulletsInClip();
|
||||
shootTime = animscripts\weaponList::shootAnimTime();
|
||||
quickTime = animscripts\weaponList::waitAfterShot();
|
||||
wait quickTime;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
1111
animscripts/setposemovement.gsc
Normal file
1111
animscripts/setposemovement.gsc
Normal file
File diff suppressed because it is too large
Load Diff
2152
animscripts/shared.gsc
Normal file
2152
animscripts/shared.gsc
Normal file
File diff suppressed because it is too large
Load Diff
715
animscripts/shoot_behavior.gsc
Normal file
715
animscripts/shoot_behavior.gsc
Normal file
@ -0,0 +1,715 @@
|
||||
#include common_scripts\utility;
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\utility;
|
||||
#include animscripts\shared;
|
||||
|
||||
// Ideally, this will be the only thread *anywhere* that decides what/where to shoot at
|
||||
// and how to shoot at it.
|
||||
|
||||
// This thread keeps three variables updated, and notifies "shoot_behavior_change" when any of them have changed.
|
||||
// They are:
|
||||
// shootEnt - an entity. aim/shoot at this if it's defined.
|
||||
// shootPos - a vector. aim/shoot towards this if shootEnt isn't defined. if not defined, stop shooting entirely and return to cover if possible.
|
||||
// Whenever shootEnt is defined, shootPos will be defined as its getShootAtPos().
|
||||
// shootStyle - how to shoot.
|
||||
// "full" (unload on the target),
|
||||
// "burst" (occasional groups of shots),
|
||||
// "semi" (occasianal single shots),
|
||||
// "single" (occasional single shots),
|
||||
// "none" (don't shoot, just aim).
|
||||
// This thread will also notify "return_to_cover" and set self.shouldReturnToCover = true if it's a good idea to do so.
|
||||
// Notify "stop_deciding_how_to_shoot" to end this thread if no longer trying to shoot.
|
||||
|
||||
decideWhatAndHowToShoot( objective )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self notify( "stop_deciding_how_to_shoot" );// just in case...
|
||||
self endon( "stop_deciding_how_to_shoot" );
|
||||
self endon( "death" );
|
||||
|
||||
assert( isdefined( objective ) );// just use "normal" if you don't know what to use
|
||||
|
||||
maps\_gameskill::resetMissTime();
|
||||
self.shootObjective = objective;
|
||||
// self.shootObjective is always "normal", "suppress", or "ambush"
|
||||
|
||||
self.shootEnt = undefined;
|
||||
self.shootPos = undefined;
|
||||
self.shootStyle = "none";
|
||||
self.fastBurst = false;
|
||||
self.shouldReturnToCover = undefined;
|
||||
|
||||
if ( !isdefined( self.changingCoverPos ) )
|
||||
self.changingCoverPos = false;
|
||||
|
||||
atCover = isDefined( self.coverNode ) && self.coverNode.type != "Cover Prone" && self.coverNode.type != "Conceal Prone";
|
||||
|
||||
if ( atCover )
|
||||
{
|
||||
// it's not safe to do some things until the next frame,
|
||||
// such as canSuppressEnemy(), which may change the state of
|
||||
// self.goodShootPos, which will screw up cover_behavior::main
|
||||
// when this is called but then stopped immediately.
|
||||
wait .05;
|
||||
}
|
||||
|
||||
prevShootEnt = self.shootEnt;
|
||||
prevShootPos = self.shootPos;
|
||||
prevShootStyle = self.shootStyle;
|
||||
|
||||
if ( !isdefined( self.has_no_ir ) )
|
||||
{
|
||||
self.a.laserOn = true;
|
||||
self animscripts\shared::updateLaserStatus();
|
||||
}
|
||||
|
||||
if ( self isSniper() )
|
||||
self resetSniperAim();
|
||||
|
||||
// only watch for incoming fire if it will be beneficial for us to return to cover when shot at.
|
||||
if ( atCover && ( !self.a.atConcealmentNode || !self canSeeEnemy() ) )
|
||||
thread watchForIncomingFire();
|
||||
thread runOnShootBehaviorEnd();
|
||||
|
||||
self.ambushEndTime = undefined;
|
||||
|
||||
prof_begin( "decideWhatAndHowToShoot" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
if ( isdefined( self.shootPosOverride ) )
|
||||
{
|
||||
if ( !isdefined( self.enemy ) )
|
||||
{
|
||||
self.shootPos = self.shootPosOverride;
|
||||
self.shootPosOverride = undefined;
|
||||
WaitABit();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.shootPosOverride = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
assert( self.shootObjective == "normal" || self.shootObjective == "suppress" || self.shootObjective == "ambush" );
|
||||
assert( !isdefined( self.shootEnt ) || isdefined( self.shootPos ) );// shootPos must be shootEnt's shootAtPos if shootEnt is defined, for convenience elsewhere
|
||||
|
||||
result = undefined;
|
||||
if ( self.weapon == "none" )
|
||||
noGunShoot();
|
||||
else if ( usingStreamgun() )
|
||||
result = streamgunShoot();
|
||||
else if ( usingRocketLauncher() )
|
||||
result = rpgShoot();
|
||||
else if ( usingSidearm() )
|
||||
result = pistolShoot();
|
||||
else if ( usingMinigun() )
|
||||
result = rifleShoot();//minigunShoot();
|
||||
else
|
||||
result = rifleShoot();
|
||||
|
||||
if ( isDefined( self.a.specialShootBehavior ) )
|
||||
[[self.a.specialShootBehavior]]();
|
||||
|
||||
|
||||
if ( checkChanged( prevShootEnt, self.shootEnt ) || ( !isdefined( self.shootEnt ) && checkChanged( prevShootPos, self.shootPos ) ) || checkChanged( prevShootStyle, self.shootStyle ) )
|
||||
self notify( "shoot_behavior_change" );
|
||||
prevShootEnt = self.shootEnt;
|
||||
prevShootPos = self.shootPos;
|
||||
prevShootStyle = self.shootStyle;
|
||||
|
||||
|
||||
// (trying to prevent many AI from doing lots of work on the same frame)
|
||||
if ( !isdefined( result ) )
|
||||
WaitABit();
|
||||
}
|
||||
|
||||
prof_end( "decideWhatAndHowToShoot" );
|
||||
}
|
||||
|
||||
WaitABit()
|
||||
{
|
||||
self endon( "enemy" );
|
||||
self endon( "done_changing_cover_pos" );
|
||||
self endon( "weapon_position_change" );
|
||||
self endon( "enemy_visible" );
|
||||
|
||||
if ( isdefined( self.shootEnt ) )
|
||||
{
|
||||
self.shootEnt endon( "death" );
|
||||
|
||||
self endon( "do_slow_things" );
|
||||
|
||||
// (want to keep self.shootPos up to date)
|
||||
wait .05;
|
||||
while ( isdefined( self.shootEnt ) )
|
||||
{
|
||||
self.shootPos = self.shootEnt getShootAtPos();
|
||||
wait .05;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self waittill( "do_slow_things" );
|
||||
}
|
||||
}
|
||||
|
||||
noGunShoot()
|
||||
{
|
||||
/#
|
||||
println( "^1Warning: AI at " + self.origin + ", entnum " + self getEntNum() + ", export " + self.export + " trying to shoot but has no gun" );
|
||||
#/
|
||||
self.shootEnt = undefined;
|
||||
self.shootPos = undefined;
|
||||
self.shootStyle = "none";
|
||||
self.shootObjective = "normal";
|
||||
}
|
||||
|
||||
shouldSuppress()
|
||||
{
|
||||
return !self isSniper() && !isShotgun( self.weapon );
|
||||
}
|
||||
|
||||
shouldShootEnemyEnt()
|
||||
{
|
||||
assert( isDefined ( self ) );
|
||||
|
||||
if ( !self canSeeEnemy() )
|
||||
return false;
|
||||
|
||||
// When not in cover, check if we can shoot at our current enemy as well
|
||||
if ( !isDefined( self.coverNode ) && !self canShootEnemy() )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
rifleShootObjectiveNormal()
|
||||
{
|
||||
if ( !shouldShootEnemyEnt() )
|
||||
{
|
||||
// enemy disappeared!
|
||||
if ( self isSniper() )
|
||||
self resetSniperAim();
|
||||
|
||||
if ( self.doingAmbush )
|
||||
{
|
||||
self.shootObjective = "ambush";
|
||||
return "retry";
|
||||
}
|
||||
|
||||
if ( !isdefined( self.enemy ) )
|
||||
{
|
||||
haveNothingToShoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
markEnemyPosInvisible();
|
||||
|
||||
if ( ( self.provideCoveringFire || randomint( 5 ) > 0 ) && shouldSuppress() )
|
||||
self.shootObjective = "suppress";
|
||||
else
|
||||
self.shootObjective = "ambush";
|
||||
return "retry";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setShootEntToEnemy();
|
||||
self setShootStyleForVisibleEnemy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rifleShootObjectiveSuppress( enemySuppressable )
|
||||
{
|
||||
if ( !enemySuppressable )
|
||||
{
|
||||
haveNothingToShoot();
|
||||
}
|
||||
else
|
||||
{
|
||||
self.shootEnt = undefined;
|
||||
self.shootPos = getEnemySightPos();
|
||||
|
||||
self setShootStyleForSuppression();
|
||||
}
|
||||
}
|
||||
|
||||
rifleShootObjectiveAmbush( enemySuppressable )
|
||||
{
|
||||
assert( self.shootObjective == "ambush" );
|
||||
|
||||
self.shootStyle = "none";
|
||||
self.shootEnt = undefined;
|
||||
|
||||
if ( !enemySuppressable )
|
||||
{
|
||||
getAmbushShootPos();
|
||||
|
||||
if ( shouldStopAmbushing() )
|
||||
{
|
||||
self.ambushEndTime = undefined;
|
||||
self notify( "return_to_cover" );
|
||||
self.shouldReturnToCover = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.shootPos = getEnemySightPos();
|
||||
|
||||
if ( self shouldStopAmbushing() )
|
||||
{
|
||||
self.ambushEndTime = undefined;
|
||||
|
||||
if ( shouldSuppress() )
|
||||
self.shootObjective = "suppress";
|
||||
|
||||
if ( randomint( 3 ) == 0 )
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
self.shouldReturnToCover = true;
|
||||
}
|
||||
return "retry";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
getAmbushShootPos()
|
||||
{
|
||||
if ( isdefined( self.enemy ) && self cansee( self.enemy ) )
|
||||
{
|
||||
setShootEntToEnemy();
|
||||
return;
|
||||
}
|
||||
|
||||
likelyEnemyDir = self getAnglesToLikelyEnemyPath();
|
||||
|
||||
if ( !isdefined( likelyEnemyDir ) )
|
||||
{
|
||||
if ( isDefined( self.coverNode ) )
|
||||
likelyEnemyDir = self.coverNode.angles;
|
||||
else if ( isdefined( self.ambushNode ) )
|
||||
likelyEnemyDir = self.ambushNode.angles;
|
||||
else if ( isdefined( self.enemy ) )
|
||||
likelyEnemyDir = vectorToAngles( self lastKnownPos( self.enemy ) - self.origin );
|
||||
else
|
||||
likelyEnemyDir = self.angles;
|
||||
}
|
||||
|
||||
dist = 1024;
|
||||
if ( isdefined( self.enemy ) )
|
||||
dist = distance( self.origin, self.enemy.origin );
|
||||
|
||||
newShootPos = self getEye() + anglesToForward( likelyEnemyDir ) * dist;
|
||||
|
||||
if ( !isdefined( self.shootPos ) || distanceSquared( newShootPos, self.shootPos ) > 5 * 5 )// avoid frequent "shoot_behavior_change" notifies
|
||||
self.shootPos = newShootPos;
|
||||
}
|
||||
|
||||
|
||||
rifleShoot()
|
||||
{
|
||||
if ( self.shootObjective == "normal" )
|
||||
{
|
||||
rifleShootObjectiveNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( shouldShootEnemyEnt() )// later, maybe we can be more realistic than just shooting at the enemy the instant he becomes visible
|
||||
{
|
||||
self.shootObjective = "normal";
|
||||
self.ambushEndTime = undefined;
|
||||
return "retry";
|
||||
}
|
||||
|
||||
markEnemyPosInvisible();
|
||||
|
||||
if ( self isSniper() )
|
||||
self resetSniperAim();
|
||||
|
||||
enemySuppressable = canSuppressEnemy();
|
||||
|
||||
if ( self.shootObjective == "suppress" || ( self.team == "allies" && !isdefined( self.enemy ) && !enemySuppressable ) )
|
||||
rifleShootObjectiveSuppress( enemySuppressable );
|
||||
else
|
||||
rifleShootObjectiveAmbush( enemySuppressable );
|
||||
}
|
||||
}
|
||||
|
||||
streamgunShoot()
|
||||
{
|
||||
if ( shouldShootEnemyEnt() )
|
||||
{
|
||||
setShootEntToEnemy();
|
||||
setShootStyle( "continuous", false );
|
||||
}
|
||||
}
|
||||
|
||||
shouldStopAmbushing()
|
||||
{
|
||||
if ( !isdefined( self.ambushEndTime ) )
|
||||
{
|
||||
if ( self isBadGuy() )
|
||||
self.ambushEndTime = gettime() + randomintrange( 10000, 60000 );
|
||||
else
|
||||
self.ambushEndTime = gettime() + randomintrange( 4000, 10000 );
|
||||
}
|
||||
return self.ambushEndTime < gettime();
|
||||
}
|
||||
|
||||
rpgShoot()
|
||||
{
|
||||
if ( !shouldShootEnemyEnt() )
|
||||
{
|
||||
markEnemyPosInvisible();
|
||||
|
||||
haveNothingToShoot();
|
||||
return;
|
||||
}
|
||||
|
||||
setShootEntToEnemy();
|
||||
self.shootStyle = "single";
|
||||
|
||||
distSqToShootPos = lengthsquared( self.origin - self.shootPos );
|
||||
// too close for RPG
|
||||
if ( distSqToShootPos < squared( 512 ) )
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
self.shouldReturnToCover = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pistolShoot()
|
||||
{
|
||||
if ( self.shootObjective == "normal" )
|
||||
{
|
||||
if ( !shouldShootEnemyEnt() )
|
||||
{
|
||||
// enemy disappeared!
|
||||
if ( !isdefined( self.enemy ) )
|
||||
{
|
||||
haveNothingToShoot();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
markEnemyPosInvisible();
|
||||
|
||||
self.shootObjective = "ambush";
|
||||
return "retry";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setShootEntToEnemy();
|
||||
self.shootStyle = "single";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( shouldShootEnemyEnt() )// later, maybe we can be more realistic than just shooting at the enemy the instant he becomes visible
|
||||
{
|
||||
self.shootObjective = "normal";
|
||||
self.ambushEndTime = undefined;
|
||||
return "retry";
|
||||
}
|
||||
|
||||
markEnemyPosInvisible();
|
||||
|
||||
self.shootEnt = undefined;
|
||||
self.shootStyle = "none";
|
||||
self.shootPos = getEnemySightPos();
|
||||
|
||||
// stop ambushing after a while
|
||||
if ( !isdefined( self.ambushEndTime ) )
|
||||
self.ambushEndTime = gettime() + randomintrange( 4000, 8000 );
|
||||
|
||||
if ( self.ambushEndTime < gettime() )
|
||||
{
|
||||
self.shootObjective = "normal";
|
||||
self.ambushEndTime = undefined;
|
||||
return "retry";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markEnemyPosInvisible()
|
||||
{
|
||||
if ( isdefined( self.enemy ) && !self.changingCoverPos && self.script != "combat" )
|
||||
{
|
||||
// make sure they're not just hiding
|
||||
if ( isAI( self.enemy ) && isdefined( self.enemy.script ) && ( self.enemy.script == "cover_stand" || self.enemy.script == "cover_crouch" ) )
|
||||
{
|
||||
if ( isdefined( self.enemy.a.coverMode ) && self.enemy.a.coverMode == "hide" )
|
||||
return;
|
||||
}
|
||||
|
||||
self.couldntSeeEnemyPos = self.enemy.origin;
|
||||
}
|
||||
}
|
||||
|
||||
watchForIncomingFire()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop_deciding_how_to_shoot" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "suppression" );
|
||||
|
||||
if ( self.suppressionMeter > self.suppressionThreshold )
|
||||
{
|
||||
if ( self readyToReturnToCover() )
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
self.shouldReturnToCover = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readyToReturnToCover()
|
||||
{
|
||||
if ( self.changingCoverPos )
|
||||
return false;
|
||||
|
||||
assert( isdefined( self.coverPosEstablishedTime ) );
|
||||
|
||||
if ( !isdefined( self.enemy ) || !self canSee( self.enemy ) )
|
||||
return true;
|
||||
|
||||
if ( gettime() < self.coverPosEstablishedTime + 800 )
|
||||
{
|
||||
// don't return to cover until we had time to fire a couple shots;
|
||||
// better to look daring than indecisive
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( isPlayer( self.enemy ) && self.enemy.health < self.enemy.maxHealth * .5 )
|
||||
{
|
||||
// give ourselves some time to take them down
|
||||
if ( gettime() < self.coverPosEstablishedTime + 3000 )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
runOnShootBehaviorEnd()
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
self waittill_any( "killanimscript", "stop_deciding_how_to_shoot"/*, "return_to_cover"*/ );
|
||||
|
||||
self.a.laserOn = false;
|
||||
self animscripts\shared::updateLaserStatus();
|
||||
}
|
||||
|
||||
checkChanged( prevval, newval )
|
||||
{
|
||||
if ( isdefined( prevval ) != isdefined( newval ) )
|
||||
return true;
|
||||
if ( !isdefined( newval ) )
|
||||
{
|
||||
assert( !isdefined( prevval ) );
|
||||
return false;
|
||||
}
|
||||
return prevval != newval;
|
||||
}
|
||||
|
||||
setShootEntToEnemy()
|
||||
{
|
||||
self.shootEnt = self.enemy;
|
||||
self.shootPos = self.shootEnt getShootAtPos();
|
||||
}
|
||||
|
||||
haveNothingToShoot()
|
||||
{
|
||||
self.shootEnt = undefined;
|
||||
self.shootPos = undefined;
|
||||
self.shootStyle = "none";
|
||||
|
||||
if ( self.doingAmbush )
|
||||
self.shootObjective = "ambush";
|
||||
|
||||
if ( !self.changingCoverPos )
|
||||
{
|
||||
self notify( "return_to_cover" );
|
||||
self.shouldReturnToCover = true;
|
||||
}
|
||||
}
|
||||
|
||||
shouldBeAJerk()
|
||||
{
|
||||
return level._gameskill == 3 && isPlayer( self.enemy );// && self shouldDoSemiForVariety();
|
||||
}
|
||||
|
||||
fullAutoRangeSq = 250 * 250;
|
||||
burstRangeSq = 900 * 900;
|
||||
singleShotRangeSq = 1600 * 1600;
|
||||
|
||||
setShootStyleForVisibleEnemy()
|
||||
{
|
||||
assert( isdefined( self.shootPos ) );
|
||||
assert( isdefined( self.shootEnt ) );
|
||||
|
||||
if ( isdefined( self.shootEnt.enemy ) && isdefined( self.shootEnt.enemy.syncedMeleeTarget ) )
|
||||
return setShootStyle( "single", false );
|
||||
|
||||
if ( self isSniper() )
|
||||
return setShootStyle( "single", false );
|
||||
|
||||
if ( isStreamgun( self.weapon ) )
|
||||
{
|
||||
return setShootStyle( "continuous", false );
|
||||
}
|
||||
|
||||
if ( isShotgun( self.weapon ) )
|
||||
{
|
||||
if ( weapon_pump_action_shotgun() )
|
||||
return setShootStyle( "single", false );
|
||||
else
|
||||
return setShootStyle( "semi", false );
|
||||
}
|
||||
|
||||
if ( weaponBurstCount( self.weapon ) > 0 )
|
||||
return setShootStyle( "burst", false );
|
||||
|
||||
distanceSq = distanceSquared( self getShootAtPos(), self.shootPos );
|
||||
|
||||
isMG = weaponClass( self.weapon ) == "mg";
|
||||
|
||||
if ( self.provideCoveringFire && isMG )
|
||||
return setShootStyle( "full", false );
|
||||
|
||||
if ( distanceSq < fullAutoRangeSq )
|
||||
{
|
||||
if ( isdefined( self.shootEnt ) && isdefined( self.shootEnt.magic_bullet_shield ) )
|
||||
return setShootStyle( "single", false );
|
||||
else
|
||||
return setShootStyle( "full", false );
|
||||
}
|
||||
else if ( distanceSq < burstRangeSq || shouldBeAJerk() )
|
||||
{
|
||||
if ( weaponIsSemiAuto( self.weapon ) || shouldDoSemiForVariety() )
|
||||
return setShootStyle( "semi", true );
|
||||
else
|
||||
return setShootStyle( "burst", true );
|
||||
}
|
||||
else if ( self.provideCoveringFire || isMG || distanceSq < singleShotRangeSq )
|
||||
{
|
||||
if ( shouldDoSemiForVariety() )
|
||||
return setShootStyle( "semi", false );
|
||||
else
|
||||
return setShootStyle( "burst", false );
|
||||
}
|
||||
|
||||
return setShootStyle( "single", false );
|
||||
}
|
||||
|
||||
setShootStyleForSuppression()
|
||||
{
|
||||
assert( isdefined( self.shootPos ) );
|
||||
|
||||
distanceSq = distanceSquared( self getShootAtPos(), self.shootPos );
|
||||
|
||||
assert( !self isSniper() );// snipers shouldn't be suppressing!
|
||||
assert( !isShotgun( self.weapon ) );// shotgun users shouldn't be suppressing!
|
||||
assert( !isStreamgun( self.weapon ) ); // streamguns shouldn't be suppressing!
|
||||
|
||||
if ( weaponIsSemiAuto( self.weapon ) )
|
||||
{
|
||||
if ( distanceSq < singleShotRangeSq )
|
||||
return setShootStyle( "semi", false );
|
||||
return setShootStyle( "single", false );
|
||||
}
|
||||
|
||||
if ( weaponClass( self.weapon ) == "mg" )
|
||||
return setShootStyle( "full", false );
|
||||
|
||||
if ( self.provideCoveringFire || distanceSq < singleShotRangeSq )
|
||||
{
|
||||
if ( shouldDoSemiForVariety() )
|
||||
return setShootStyle( "semi", false );
|
||||
else
|
||||
return setShootStyle( "burst", false );
|
||||
}
|
||||
|
||||
return setShootStyle( "single", false );
|
||||
}
|
||||
|
||||
setShootStyle( style, fastBurst )
|
||||
{
|
||||
self.shootStyle = style;
|
||||
self.fastBurst = fastBurst;
|
||||
}
|
||||
|
||||
shouldDoSemiForVariety()
|
||||
{
|
||||
if ( weaponClass( self.weapon ) != "rifle" )
|
||||
return false;
|
||||
|
||||
if ( self.team != "allies" )
|
||||
return false;
|
||||
|
||||
// true randomness isn't safe, because that will cause frequent shoot_behavior_change notifies.
|
||||
// fake the randomness in a way that won't change frequently.
|
||||
changeFrequency = safemod( int( self.origin[ 1 ] ), 10000 ) + 2000;
|
||||
fakeTimeValue = int( self.origin[ 0 ] ) + gettime();
|
||||
|
||||
return fakeTimeValue %( 2 * changeFrequency ) > changeFrequency;
|
||||
}
|
||||
|
||||
resetSniperAim()
|
||||
{
|
||||
assert( self isSniper() );
|
||||
self.sniperShotCount = 0;
|
||||
self.sniperHitCount = 0;
|
||||
|
||||
thread sniper_glint_behavior();
|
||||
}
|
||||
|
||||
sniper_glint_behavior()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "enemy" );
|
||||
self endon( "return_to_cover" );
|
||||
self notify( "new_glint_thread" );
|
||||
self endon( "new_glint_thread" );
|
||||
|
||||
assertex( self isSniper(), "Not a sniper!" );
|
||||
if ( !isdefined( level._effect[ "sniper_glint" ] ) )
|
||||
{
|
||||
println( "^3Warning, sniper glint is not setup for sniper with classname " + self.classname );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !isAlive( self.enemy ) )
|
||||
return;
|
||||
|
||||
//if ( !isPlayer( self.enemy ) )
|
||||
// return;
|
||||
|
||||
fx = getfx( "sniper_glint" );
|
||||
|
||||
wait 0.2;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( self.weapon == self.primaryweapon && player_sees_my_scope() )
|
||||
{
|
||||
if ( distanceSquared( self.origin, self.enemy.origin ) > 256 * 256 )
|
||||
PlayFXOnTag( fx, self, "tag_flash" );
|
||||
|
||||
timer = randomfloatrange( 3, 5 );
|
||||
wait( timer );
|
||||
}
|
||||
wait( 0.2 );
|
||||
}
|
||||
}
|
||||
|
957
animscripts/snowmobile.gsc
Normal file
957
animscripts/snowmobile.gsc
Normal file
@ -0,0 +1,957 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\_utility;
|
||||
#include maps\_anim;
|
||||
#include animscripts\shared;
|
||||
#include animscripts\utility;
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
CONST_MPHCONVERSION = 17.6;
|
||||
|
||||
main()
|
||||
{
|
||||
assert( isdefined( self.ridingvehicle ) );
|
||||
|
||||
self.current_event = "none";
|
||||
self.shoot_while_driving_thread = undefined;
|
||||
|
||||
self snowmobile_geton();
|
||||
|
||||
if ( isdefined( self.drivingvehicle ) )
|
||||
main_driver();
|
||||
else
|
||||
main_passenger();
|
||||
}
|
||||
|
||||
snowmobile_geton()
|
||||
{
|
||||
self.grenadeawareness = 0;
|
||||
self.a.pose = "crouch";
|
||||
self disable_surprise();
|
||||
self.allowpain = false;
|
||||
|
||||
self.getOffVehicleFunc = ::snowmobile_getoff;
|
||||
self.specialDeathFunc = animscripts\snowmobile::snowmobile_normal_death;
|
||||
self.disableBulletWhizbyReaction = true;
|
||||
}
|
||||
|
||||
snowmobile_getoff()
|
||||
{
|
||||
self.allowpain = true;
|
||||
|
||||
self.getOffVehicleFunc = undefined;
|
||||
self.specialDeathFunc = undefined;
|
||||
self.a.specialShootBehavior = undefined;
|
||||
self.disableBulletWhizbyReaction = undefined;
|
||||
}
|
||||
|
||||
|
||||
|
||||
main_driver()
|
||||
{
|
||||
driver_shooting = self.ridingvehicle.driver_shooting || self.ridingvehicle.riders.size == 1;
|
||||
snowmobile_setanim_driver( driver_shooting );
|
||||
|
||||
if ( driver_shooting )
|
||||
{
|
||||
placeweaponon( self.primaryweapon, "left" );
|
||||
|
||||
self.rightaimlimit = 90;
|
||||
self.leftaimlimit = -90;
|
||||
self setanimaimweight( 1, 0.2 );
|
||||
|
||||
self thread snowmobile_trackshootentorpos_driver();
|
||||
self thread snowmobile_loop_driver_shooting();
|
||||
}
|
||||
else
|
||||
{
|
||||
placeweaponon( self.primaryweapon, "none" );
|
||||
|
||||
self thread snowmobile_loop_driver();
|
||||
}
|
||||
|
||||
snowmobile_handle_events( "driver" );
|
||||
}
|
||||
|
||||
main_passenger()
|
||||
{
|
||||
snowmobile_setanim_passenger( self.ridingvehicle.passenger_shooting );
|
||||
|
||||
if ( self.ridingvehicle.passenger_shooting )
|
||||
{
|
||||
self.rightaimlimit = 180;
|
||||
self.leftaimlimit = -180;
|
||||
self.diraimlimit = 1;
|
||||
self setanimaimweight( 1, 0.2 );
|
||||
|
||||
self thread snowmobile_trackshootentorpos_passenger();
|
||||
self thread snowmobile_loop_passenger_shooting();
|
||||
}
|
||||
else
|
||||
{
|
||||
self thread snowmobile_loop_passenger();
|
||||
}
|
||||
|
||||
snowmobile_handle_events( "passenger" );
|
||||
}
|
||||
|
||||
snowmobile_loop_driver()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
current_anim = "left2right";
|
||||
|
||||
anim_length = [];
|
||||
anim_length[ "left2right" ] = getanimlength( animarray( "left2right" ) );
|
||||
anim_length[ "right2left" ] = getanimlength( animarray( "right2left" ) );
|
||||
|
||||
self setanimknoball( %sm_turn, %body, 1, 0 );
|
||||
self setanim( animarray( "drive" ), 1, 0 );
|
||||
self setanimknob( animarray( current_anim ), 1, 0 );
|
||||
self setanimtime( animarray( current_anim ), 0.5 );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( self.ridingvehicle.steering_enable )
|
||||
{
|
||||
steering = 0.5*(1 + maps\_vehicle::update_steering( self.ridingvehicle ));
|
||||
|
||||
anim_time = self getanimtime( animarray( current_anim ) );
|
||||
if ( current_anim == "right2left" )
|
||||
anim_time = 1 - anim_time;
|
||||
|
||||
rate = 20*abs( anim_time - steering );
|
||||
|
||||
if ( anim_time < steering )
|
||||
{
|
||||
current_anim = "left2right";
|
||||
rate *= anim_length[ "left2right" ];
|
||||
}
|
||||
else
|
||||
{
|
||||
current_anim = "right2left";
|
||||
rate *= anim_length[ "right2left" ];
|
||||
anim_time = 1 - anim_time;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current_anim = "left2right";
|
||||
rate = 0;
|
||||
anim_time = 0.5;
|
||||
}
|
||||
|
||||
self setanimknoblimited( animarray( current_anim ), 1, 0.1, rate );
|
||||
self setanimtime( animarray( current_anim ), anim_time );
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_loop_passenger()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self setanimknoball( animarray( "hide" ), %body, 1, 0 );
|
||||
self setanimknob( animarray( "drive" ), 1, 0 );
|
||||
|
||||
for (;;)
|
||||
{
|
||||
steering = maps\_vehicle::update_steering( self.ridingvehicle );
|
||||
self setanimlimited( %sm_lean, abs( steering ), 0.05 );
|
||||
if ( steering >= 0 ) {
|
||||
self setanimknoblimited( animarray( "lean_right" ), 1, 0.05 );
|
||||
} else {
|
||||
self setanimknoblimited( animarray( "lean_left" ), 1, 0.05 );
|
||||
}
|
||||
|
||||
wait 0.05;
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_loop_driver_shooting()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
leanblendtime = .05;
|
||||
reloadFinishedTime = 0;
|
||||
|
||||
self setanimknoball( %sm_aiming, %body, 1, 0 );
|
||||
self setanimknob( animarray( "idle" ), 1, 0 );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( self.current_event != "none" )
|
||||
{
|
||||
self waittill( "snowmobile_event_finished" );
|
||||
continue;
|
||||
}
|
||||
|
||||
steering = maps\_vehicle::update_steering( self.ridingvehicle );
|
||||
center_steering = 1 - abs( steering );
|
||||
left_steering = max( 0, 0 - steering );
|
||||
right_steering = max( 0, steering );
|
||||
|
||||
self setanimlimited( animarray( "straight_level_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "straight_level_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "straight_level_right" ), right_steering, leanblendtime );
|
||||
|
||||
if ( self.bulletsinclip <= 0 )
|
||||
{
|
||||
self animscripts\weaponList::RefillClip();
|
||||
reloadFinishedTime = gettime() + 3000;
|
||||
}
|
||||
|
||||
if ( reloadFinishedTime <= gettime() )
|
||||
snowmobile_start_shooting();
|
||||
|
||||
self setanimknoblimited( animarray( "add_aim_left_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_left_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_left_right" ), right_steering, leanblendtime );
|
||||
|
||||
self setanimknoblimited( animarray( "add_aim_right_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_right_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_right_right" ), right_steering, leanblendtime );
|
||||
|
||||
self thread snowmobile_stop_shooting();
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_loop_passenger_shooting()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
leanblendtime = .05;
|
||||
|
||||
self setanimknoball( %sm_aiming, %body, 1, 0 );
|
||||
self setanimknob( animarray( "idle" ), 1, 0 );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( self.current_event != "none" )
|
||||
{
|
||||
self waittill( "snowmobile_event_finished" );
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( snowmobile_reload() )
|
||||
continue;
|
||||
|
||||
steering = maps\_vehicle::update_steering( self.ridingvehicle );
|
||||
center_steering = 1 - abs( steering );
|
||||
left_steering = max( 0, 0 - steering );
|
||||
right_steering = max( 0, steering );
|
||||
|
||||
self setanimlimited( animarray( "straight_level_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "straight_level_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "straight_level_right" ), right_steering, leanblendtime );
|
||||
|
||||
snowmobile_start_shooting();
|
||||
|
||||
self setanimlimited( animarray( "aim_left_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "aim_left_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "aim_left_right" ), right_steering, leanblendtime );
|
||||
|
||||
self setanimlimited( animarray( "aim_right_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "aim_right_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "aim_right_right" ), right_steering, leanblendtime );
|
||||
|
||||
self setanimlimited( animarray( "add_aim_backleft_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_backleft_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_backleft_right" ), right_steering, leanblendtime );
|
||||
|
||||
self setanimlimited( animarray( "add_aim_backright_center" ), center_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_backright_left" ), left_steering, leanblendtime );
|
||||
self setanimlimited( animarray( "add_aim_backright_right" ), right_steering, leanblendtime );
|
||||
|
||||
if ( isplayer( self.enemy ) )
|
||||
self updateplayersightaccuracy();
|
||||
|
||||
wait( 0.05 );
|
||||
self thread snowmobile_stop_shooting(); // stop shooting on the next frame unless snowmobile_start_shooting is called again
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_do_event( animation )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
self.ridingvehicle.steering_enable = false;
|
||||
self setflaggedanimknoblimitedrestart( "snowmobile_event", animation, 1, 0.17 );
|
||||
donotetracks( "snowmobile_event", ::snowmobile_waitfor_start_lean );
|
||||
self setanimknoblimited( animarray( "event_restore" ), 1, 0.1 );
|
||||
self.ridingvehicle.steering_enable = true;
|
||||
self.current_event = "none";
|
||||
self notify( "snowmobile_event_finished" );
|
||||
}
|
||||
|
||||
snowmobile_handle_events( rider )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "killanimscript" );
|
||||
|
||||
snowmobile = self.ridingvehicle;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( snowmobile.event[ "jump" ][ rider ] )
|
||||
{
|
||||
snowmobile.event[ "jump" ][ rider ] = false;
|
||||
self notify( "snowmobile_event_occurred" );
|
||||
self.current_event = "jump";
|
||||
snowmobile.steering_enable = false;
|
||||
self setflaggedanimknoblimitedrestart( "jump", animarray( "event_jump" ), 1, 0.17 );
|
||||
}
|
||||
|
||||
if ( snowmobile.event[ "bump" ][ rider ] )
|
||||
{
|
||||
snowmobile.event[ "bump" ][ rider ] = false;
|
||||
self notify( "snowmobile_event_occurred" );
|
||||
if ( self.current_event != "bump_big" )
|
||||
self thread snowmobile_do_event( animarray( "event_bump" ) );
|
||||
}
|
||||
|
||||
if ( snowmobile.event[ "bump_big" ][ rider ] )
|
||||
{
|
||||
snowmobile.event[ "bump_big" ][ rider ] = false;
|
||||
self notify( "snowmobile_event_occurred" );
|
||||
self.current_event = "bump_big";
|
||||
self thread snowmobile_do_event( animarray( "event_bump_big" ) );
|
||||
}
|
||||
|
||||
if ( snowmobile.event[ "sway_left" ][ rider ] )
|
||||
{
|
||||
snowmobile.event[ "sway_left" ][ rider ] = false;
|
||||
self notify( "snowmobile_event_occurred" );
|
||||
if ( self.current_event != "bump_big" )
|
||||
self thread snowmobile_do_event( animarray( "event_sway" )[ "left" ] );
|
||||
}
|
||||
|
||||
if ( snowmobile.event[ "sway_right" ][ rider ] )
|
||||
{
|
||||
snowmobile.event[ "sway_right" ][ rider ] = false;
|
||||
self notify( "snowmobile_event_occurred" );
|
||||
if ( self.current_event != "bump_big" )
|
||||
self thread snowmobile_do_event( animarray( "event_sway" )[ "right" ] );
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_start_shooting()
|
||||
{
|
||||
self notify( "want_shoot_while_driving" );
|
||||
|
||||
self setAnim( %sm_add_fire, 1, 0.2 );
|
||||
|
||||
if ( isdefined( self.shoot_while_driving_thread ) )
|
||||
return;
|
||||
self.shoot_while_driving_thread = true;
|
||||
|
||||
self thread snowmobile_decide_shoot();
|
||||
self thread snowmobile_shoot();
|
||||
}
|
||||
|
||||
snowmobile_stop_shooting()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "want_shoot_while_driving" );
|
||||
|
||||
wait .05;
|
||||
|
||||
self notify( "end_shoot_while_driving" );
|
||||
self.shoot_while_driving_thread = undefined;
|
||||
self clearAnim( %sm_add_fire, 0.2 );
|
||||
}
|
||||
|
||||
snowmobile_decide_shoot()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "end_shoot_while_driving" );
|
||||
|
||||
self.a.specialShootBehavior = ::snowmobileShootBehavior;
|
||||
|
||||
snowmobile_decide_shoot_internal();
|
||||
|
||||
self.shoot_while_driving_thread = undefined; // start shooting again the next time we want it
|
||||
}
|
||||
|
||||
snowmobile_decide_shoot_internal()
|
||||
{
|
||||
// events stop the shooting animations, so stop shooting when they happen
|
||||
self endon( "snowmobile_event_occurred" );
|
||||
|
||||
self animscripts\shoot_behavior::decideWhatAndHowToShoot( "normal" );
|
||||
}
|
||||
|
||||
|
||||
snowmobileShootBehavior()
|
||||
{
|
||||
if ( !isdefined( self.enemy ) )
|
||||
{
|
||||
self.shootent = undefined;
|
||||
self.shootpos = undefined;
|
||||
self.shootstyle = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
self.shootent = self.enemy;
|
||||
self.shootpos = self.enemy getShootAtPos();
|
||||
distSq = distanceSquared( self.origin, self.enemy.origin );
|
||||
|
||||
if ( distSq < 1000*1000 )
|
||||
self.shootstyle = "full";
|
||||
else if ( distSq < 2000*2000 )
|
||||
self.shootstyle = "burst";
|
||||
else
|
||||
self.shootstyle = "single";
|
||||
|
||||
|
||||
if ( isdefined( self.enemy.vehicle ) )
|
||||
{
|
||||
shoot_ahead_speed_multiplier = 0.5;
|
||||
//shoot_ahead_random_spread = 50;
|
||||
|
||||
vehicle = self.shootent.vehicle;
|
||||
snowmobile = self.ridingvehicle;
|
||||
delta = snowmobile.origin - vehicle.origin;
|
||||
forward = anglestoforward( vehicle.angles );
|
||||
right = anglestoright( vehicle.angles );
|
||||
dot = vectordot( delta, forward );
|
||||
if ( dot < 0 )
|
||||
{
|
||||
speed = vehicle vehicle_getspeed() * shoot_ahead_speed_multiplier;
|
||||
speed *= CONST_MPHCONVERSION;
|
||||
|
||||
if ( speed > 50 )
|
||||
{
|
||||
sideness = vectordot( delta, right );
|
||||
sideness /= 3;
|
||||
if ( sideness > 128 )
|
||||
sideness = 128;
|
||||
else if ( sideness < -128 )
|
||||
sideness = -128;
|
||||
// flip it so guys farther to the side shoot in front of you
|
||||
if ( sideness > 0 )
|
||||
sideness = 128 - sideness;
|
||||
else
|
||||
sideness = -128 - sideness;
|
||||
|
||||
self.shootent = undefined;
|
||||
self.shootpos = vehicle.origin + speed * forward + sideness * right;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
snowmobile_shoot()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "end_shoot_while_driving" );
|
||||
|
||||
self notify( "doing_shootWhileDriving" );
|
||||
self endon( "doing_shootWhileDriving" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( !self.bulletsInClip )
|
||||
{
|
||||
wait 0.5;
|
||||
continue;
|
||||
}
|
||||
|
||||
self animscripts\combat_utility::shootUntilShootBehaviorChange();
|
||||
// self clearAnim( %exposed_modern, 0.2 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_reload()
|
||||
{
|
||||
if ( !self.ridingvehicle.steering_enable )
|
||||
return false;
|
||||
|
||||
if ( !self animscripts\combat_utility::needtoreload( 0 ) )
|
||||
return false;
|
||||
|
||||
if ( !usingRifleLikeWeapon() )
|
||||
return false;
|
||||
|
||||
snowmobile_reload_internal();
|
||||
|
||||
// notify "abort_reload" in case the reload didn't finish. works with handledropclip() in shared.gsc
|
||||
self notify( "abort_reload" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
snowmobile_reload_internal()
|
||||
{
|
||||
self endon( "snowmobile_event_occurred" );
|
||||
|
||||
self.stop_aiming_for_reload = true;
|
||||
self waittill( "start_blending_reload" );
|
||||
|
||||
self setanim( %sm_aiming, 0, 0.25 );
|
||||
self setflaggedanimrestart( "gun_down", animarray( "gun_down" ), 1, 0.25 );
|
||||
DoNoteTracks( "gun_down" );
|
||||
self clearAnim( animarray( "gun_down" ), 0 );
|
||||
|
||||
self setflaggedanimknoballrestart( "reload_anim", animarray( "reload" ), %body, 1, 0.25 );
|
||||
DoNoteTracks( "reload_anim" );
|
||||
self clearAnim( %sm_reload, 0.2 );
|
||||
|
||||
self setflaggedanimrestart( "gun_up", animarray( "gun_up" ), 1, 0.25 );
|
||||
self.gun_up_for_reload = true;
|
||||
DoNoteTracks( "gun_up", ::snowmobile_waitfor_start_aim );
|
||||
|
||||
|
||||
self.stop_aiming_for_reload = undefined;
|
||||
self clearAnim( %sm_reload, 0.1 );
|
||||
self setanim( %sm_aiming, 1, 0.1 );
|
||||
|
||||
if ( isdefined( self.gun_up_for_reload ) )
|
||||
{
|
||||
self.gun_up_for_reload = undefined;
|
||||
DoNoteTracks( "gun_up", ::snowmobile_waitfor_end );
|
||||
self clearAnim( animarray( "gun_up" ), 0 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_waitfor_start_aim( note )
|
||||
{
|
||||
if ( note == "start_aim" )
|
||||
return true;
|
||||
}
|
||||
|
||||
snowmobile_waitfor_end( note )
|
||||
{
|
||||
if ( note == "end" )
|
||||
return true;
|
||||
}
|
||||
|
||||
snowmobile_waitfor_start_lean( note )
|
||||
{
|
||||
if ( note == "start_lean" )
|
||||
return true;
|
||||
}
|
||||
|
||||
snowmobile_trackshootentorpos_driver()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop tracking" );
|
||||
|
||||
/#
|
||||
assert( !isdefined( self.trackLoopThread ) );
|
||||
self.trackLoopThread = thisthread;
|
||||
self.trackLoopThreadType = "snowmobile_trackshootentorpos_driver";
|
||||
#/
|
||||
|
||||
aimblendtime = .05;
|
||||
|
||||
maxyawdeltachange = 8;// max change in yaw in 1 frame
|
||||
prevyawdelta = 0;
|
||||
yawdelta = 0;
|
||||
|
||||
firstframe = true;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
incranimaimweight();
|
||||
|
||||
selfshootatpos = ( self.origin[ 0 ], self.origin[ 1 ], self geteye()[ 2 ] );
|
||||
|
||||
shootpos = self.shootpos;
|
||||
if ( isdefined( self.shootent ) )
|
||||
shootpos = self.shootent getshootatpos();
|
||||
|
||||
if ( !isdefined( shootpos ) )
|
||||
{
|
||||
assert( !isdefined( self.shootent ) );
|
||||
|
||||
yawdelta = 0;
|
||||
likelyenemydir = self getanglestolikelyenemypath();
|
||||
if ( isdefined( likelyenemydir ) )
|
||||
{
|
||||
yawdelta = angleclamp180( self.angles[ 1 ] - likelyenemydir[ 1 ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vectortoshootpos = shootpos - selfshootatpos;
|
||||
anglestoshootpos = vectortoangles( vectortoshootpos );
|
||||
|
||||
yawdelta = self.angles[ 1 ] - anglestoshootpos[ 1 ];
|
||||
yawdelta = angleclamp180( yawdelta );
|
||||
}
|
||||
|
||||
assert( self.rightaimlimit >= 0 );
|
||||
assert( self.leftaimlimit <= 0 );
|
||||
if ( yawdelta > self.rightaimlimit || yawdelta < self.leftaimlimit )
|
||||
yawdelta = 0;
|
||||
|
||||
if ( firstframe )
|
||||
{
|
||||
firstframe = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
yawdeltachange = yawdelta - prevyawdelta;
|
||||
|
||||
if ( abs( yawdeltachange ) > maxyawdeltachange )
|
||||
yawdelta = prevyawdelta + maxyawdeltachange * sign( yawdeltachange );
|
||||
}
|
||||
|
||||
prevyawdelta = yawdelta;
|
||||
|
||||
weight4 = min( max( 0 - yawdelta, 0 ), 90 ) / 90 * self.a.aimweight;
|
||||
weight6 = min( max( yawdelta, 0 ), 90 ) / 90 * self.a.aimweight;
|
||||
|
||||
self setanimlimited( %sm_aim_4, weight4, aimblendtime );
|
||||
self setanimlimited( %sm_aim_6, weight6, aimblendtime );
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_trackshootentorpos_passenger()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "stop tracking" );
|
||||
|
||||
/#
|
||||
assert( !isdefined( self.trackLoopThread ) );
|
||||
self.trackLoopThread = thisthread;
|
||||
self.trackLoopThreadType = "snowmobile_trackshootentorpos_passenger";
|
||||
#/
|
||||
|
||||
aimblendtime = .05;
|
||||
|
||||
maxyawdeltachange_default = 5;// max change in yaw in 1 frame
|
||||
maxyawdeltachange_fast = 20;
|
||||
maxyawdeltachange_reload = 15;
|
||||
yawdelta_overshoot_begin = 40;
|
||||
yawdelta_overshoot_end = 30;
|
||||
|
||||
prevyawdelta = 0;
|
||||
yawdelta = 0;
|
||||
|
||||
firstframe = true;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
incranimaimweight();
|
||||
|
||||
selfshootatpos = ( self.origin[ 0 ], self.origin[ 1 ], self geteye()[ 2 ] );
|
||||
|
||||
shootpos = self.shootpos;
|
||||
if ( isdefined( self.shootent ) )
|
||||
shootpos = self.shootent getshootatpos();
|
||||
|
||||
if ( !isdefined( shootpos ) )
|
||||
{
|
||||
assert( !isdefined( self.shootent ) );
|
||||
|
||||
yawdelta = 0;
|
||||
likelyenemydir = self getanglestolikelyenemypath();
|
||||
if ( isdefined( likelyenemydir ) )
|
||||
{
|
||||
yawdelta = angleclamp180( self.angles[ 1 ] - likelyenemydir[ 1 ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vectortoshootpos = shootpos - selfshootatpos;
|
||||
anglestoshootpos = vectortoangles( vectortoshootpos );
|
||||
|
||||
yawdelta = self.angles[ 1 ] - anglestoshootpos[ 1 ];
|
||||
yawdelta = angleclamp180( yawdelta );
|
||||
|
||||
//line( selfshootatpos, shootpos );
|
||||
}
|
||||
|
||||
assert( self.diraimlimit == 1 || self.diraimlimit == -1 );
|
||||
|
||||
if ( isdefined( self.stop_aiming_for_reload ) || ( yawdelta > 0 && ( yawdelta - self.rightaimlimit ) * self.diraimlimit > 0 ) || ( yawdelta < 0 && ( yawdelta - self.leftaimlimit ) * self.diraimlimit < 0 ) )
|
||||
yawdelta = 0;
|
||||
|
||||
if ( firstframe )
|
||||
{
|
||||
firstframe = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( prevyawdelta < -180 + yawdelta_overshoot_begin && yawdelta > 180 - yawdelta_overshoot_end )
|
||||
yawdelta = -179;
|
||||
if ( prevyawdelta > 180 - yawdelta_overshoot_begin && yawdelta < -180 + yawdelta_overshoot_end )
|
||||
yawdelta = 179;
|
||||
|
||||
yawdeltachange = yawdelta - prevyawdelta;
|
||||
|
||||
maxyawdeltachange = (maxyawdeltachange_fast - maxyawdeltachange_default) * abs( yawdeltachange ) / 180 + maxyawdeltachange_default;
|
||||
if ( isdefined( self.stop_aiming_for_reload ) )
|
||||
{
|
||||
maxyawdeltachange = maxyawdeltachange_reload;
|
||||
if ( abs( prevyawdelta ) < 45 )
|
||||
self notify( "start_blending_reload" );
|
||||
}
|
||||
|
||||
if ( abs( yawdeltachange ) > maxyawdeltachange )
|
||||
yawdelta = prevyawdelta + maxyawdeltachange * sign( yawdeltachange );
|
||||
}
|
||||
|
||||
prevyawdelta = yawdelta;
|
||||
|
||||
weight1 = max( -90 - yawdelta, 0 ) / 90 * self.a.aimweight;
|
||||
weight4 = min( max( 0 - yawdelta, 0 ), 90 ) / 90 * self.a.aimweight;
|
||||
weight5 = max( 90 - abs( yawdelta ), 0 ) / 90 * self.a.aimweight;
|
||||
weight6 = min( max( yawdelta, 0 ), 90 ) / 90 * self.a.aimweight;
|
||||
weight3 = max( -90 + yawdelta, 0 ) / 90 * self.a.aimweight;
|
||||
|
||||
self setanimlimited( %sm_aim_1, weight1, aimblendtime );
|
||||
self setanimlimited( %sm_aim_4_delta, weight4, aimblendtime );
|
||||
self setanimlimited( %sm_aim_5_delta, weight5, aimblendtime );
|
||||
self setanimlimited( %sm_aim_6_delta, weight6, aimblendtime );
|
||||
self setanimlimited( %sm_aim_3, weight3, aimblendtime );
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
snowmobile_get_death_anim( deathAnims, deathAnimDirs, goalDir )
|
||||
{
|
||||
bestDeathAnim = undefined;
|
||||
secondBestDeathAnim = undefined;
|
||||
bestDeathAnimDiff = 0;
|
||||
for ( i = 0; i < deathAnims.size; i++ )
|
||||
{
|
||||
diff = AbsAngleClamp180( goalDir - deathAnimDirs[i] );
|
||||
if ( !isdefined( bestDeathAnim ) || diff < bestDeathAnimDiff )
|
||||
{
|
||||
secondBestDeathAnim = bestDeathAnim;
|
||||
|
||||
bestDeathAnim = deathAnims[i];
|
||||
bestDeathAnimDiff = diff;
|
||||
}
|
||||
else if ( !isdefined( secondBestDeathAnim ) )
|
||||
{
|
||||
secondBestDeathAnim = deathAnims[i];
|
||||
}
|
||||
}
|
||||
assert( isdefined( bestDeathAnim ) );
|
||||
assert( isdefined( secondBestDeathAnim ) );
|
||||
|
||||
deathAnim = bestDeathAnim;
|
||||
if ( isDefined( anim.prevSnowmobileDeath ) && deathAnim == anim.prevSnowmobileDeath && gettime() - anim.prevSnowmobileDeathTime < 500 )
|
||||
deathAnim = secondBestDeathAnim;
|
||||
anim.prevSnowmobileDeath = deathAnim;
|
||||
anim.prevSnowmobileDeathTime = gettime();
|
||||
|
||||
return deathAnim;
|
||||
}
|
||||
|
||||
snowmobile_death_launchslide()
|
||||
{
|
||||
snowmobile = self.ridingvehicle;
|
||||
assert( isdefined( snowmobile ) );
|
||||
|
||||
velocity = snowmobile.prevFrameVelocity;
|
||||
velocity = ( velocity[0], velocity[1], randomfloatrange( 200, 400 ) ) * .75;
|
||||
//println( length( velocity ) );
|
||||
if ( lengthSquared( velocity ) > 1000 * 1000 )
|
||||
velocity = vectornormalize( velocity ) * 1000;
|
||||
|
||||
model = spawn( "script_origin", self.origin );
|
||||
model moveSlide( ( 0, 0, 40 ), 15, velocity );
|
||||
self linkto( model );
|
||||
|
||||
model thread deleteShortly();
|
||||
}
|
||||
|
||||
snowmobile_normal_death()
|
||||
{
|
||||
//self snowmobile_death_launchslide();
|
||||
|
||||
deathAnims = [];
|
||||
deathAnims[0] = level._scr_anim[ "snowmobile" ][ "small" ][ "death" ][ "back" ];
|
||||
deathAnims[1] = level._scr_anim[ "snowmobile" ][ "small" ][ "death" ][ "right" ];
|
||||
deathAnims[2] = level._scr_anim[ "snowmobile" ][ "small" ][ "death" ][ "left" ];
|
||||
deathAnimDirs = [];
|
||||
deathAnimDirs[0] = -180;
|
||||
deathAnimDirs[1] = -90;
|
||||
deathAnimDirs[2] = 90;
|
||||
|
||||
deathAnim = snowmobile_get_death_anim( deathAnims, deathAnimDirs, self.damageyaw );
|
||||
|
||||
animscripts\death::playDeathAnim( deathAnim );
|
||||
return true;
|
||||
}
|
||||
|
||||
snowmobile_collide_death()
|
||||
{
|
||||
snowmobile = self.ridingvehicle;
|
||||
if ( !isdefined( snowmobile ) )
|
||||
return snowmobile_normal_death();
|
||||
|
||||
velocity = snowmobile.prevFrameVelocity;
|
||||
|
||||
self snowmobile_death_launchslide();
|
||||
|
||||
angles = vectortoangles( velocity );
|
||||
delta = AngleClamp180( angles[1] - self.angles[1] );
|
||||
|
||||
deathAnims = [];
|
||||
deathAnims[0] = level._scr_anim[ "snowmobile" ][ "big" ][ "death" ][ "back" ];
|
||||
deathAnims[1] = level._scr_anim[ "snowmobile" ][ "big" ][ "death" ][ "left" ];
|
||||
deathAnims[2] = level._scr_anim[ "snowmobile" ][ "big" ][ "death" ][ "front" ];
|
||||
deathAnims[3] = level._scr_anim[ "snowmobile" ][ "big" ][ "death" ][ "right" ];
|
||||
deathAnimDirs = [];
|
||||
deathAnimDirs[0] = -180;
|
||||
deathAnimDirs[1] = -90;
|
||||
deathAnimDirs[2] = 0;
|
||||
deathAnimDirs[3] = 90;
|
||||
|
||||
deathAnim = snowmobile_get_death_anim( deathAnims, deathAnimDirs, delta );
|
||||
|
||||
animscripts\death::playDeathAnim( deathAnim );
|
||||
return true;
|
||||
}
|
||||
|
||||
deleteShortly()
|
||||
{
|
||||
prevorg = self.origin;
|
||||
for ( i = 0; i < 60; i++ )
|
||||
{
|
||||
wait .05;
|
||||
line(self.origin,prevorg);
|
||||
prevorg = self.origin;
|
||||
}
|
||||
wait 3;
|
||||
if ( isdefined( self ) )
|
||||
self delete();
|
||||
}
|
||||
|
||||
|
||||
snowmobile_setanim_common( seat )
|
||||
{
|
||||
self.a.array[ "idle" ] = level._scr_anim[ "snowmobile" ][ seat ][ "idle" ];
|
||||
self.a.array[ "drive" ] = level._scr_anim[ "snowmobile" ][ seat ][ "drive" ];
|
||||
|
||||
self.a.array[ "fire" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "single" ] = array( level._scr_anim[ "snowmobile" ][ seat ][ "single" ] );
|
||||
|
||||
self.a.array[ "burst2" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "burst3" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "burst4" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "burst5" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "burst6" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
|
||||
self.a.array[ "semi2" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "semi3" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "semi4" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
self.a.array[ "semi5" ] = level._scr_anim[ "snowmobile" ][ seat ][ "fire" ];
|
||||
}
|
||||
|
||||
snowmobile_setanim_driver( shooting )
|
||||
{
|
||||
self.a.array = [];
|
||||
|
||||
snowmobile_setanim_common( "driver" );
|
||||
|
||||
self.a.array[ "left2right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "left2right" ];
|
||||
self.a.array[ "right2left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "right2left" ];
|
||||
|
||||
self.a.array[ "straight_level_left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "straight_level" ][ "left" ];
|
||||
self.a.array[ "straight_level_center" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "straight_level" ][ "center" ];
|
||||
self.a.array[ "straight_level_right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "straight_level" ][ "right" ];
|
||||
self.a.array[ "add_aim_left_left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_left" ][ "left" ];
|
||||
self.a.array[ "add_aim_left_center" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_left" ][ "center" ];
|
||||
self.a.array[ "add_aim_left_right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_left" ][ "right" ];
|
||||
self.a.array[ "add_aim_right_left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_right" ][ "left" ];
|
||||
self.a.array[ "add_aim_right_center" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_right" ][ "center" ];
|
||||
self.a.array[ "add_aim_right_right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "add_aim_right" ][ "right" ];
|
||||
|
||||
if ( shooting )
|
||||
{
|
||||
self.a.array["event_jump"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "shoot_jump" ];
|
||||
self.a.array["event_bump"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "shoot_bump" ];
|
||||
self.a.array["event_bump_big"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "shoot_bump_big" ];
|
||||
self.a.array["event_sway"] = [];
|
||||
self.a.array["event_sway"][ "left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "shoot_sway_left" ];
|
||||
self.a.array["event_sway"][ "right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "shoot_sway_right" ];
|
||||
|
||||
self.a.array["event_restore"] = %sm_aiming;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.array["event_jump"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "drive_jump" ];
|
||||
self.a.array["event_bump"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "drive_bump" ];
|
||||
self.a.array["event_bump_big"] = level._scr_anim[ "snowmobile" ][ "driver" ][ "drive_bump_big" ];
|
||||
self.a.array["event_sway"] = [];
|
||||
self.a.array["event_sway"][ "left" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "drive_sway_left" ];
|
||||
self.a.array["event_sway"][ "right" ] = level._scr_anim[ "snowmobile" ][ "driver" ][ "drive_sway_right" ];
|
||||
|
||||
self.a.array["event_restore"] = %sm_turn;
|
||||
}
|
||||
}
|
||||
|
||||
snowmobile_setanim_passenger( shooting )
|
||||
{
|
||||
self.a.array = [];
|
||||
|
||||
snowmobile_setanim_common( "passenger" );
|
||||
|
||||
self.a.array[ "hide" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide" ];
|
||||
self.a.array[ "lean_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_lean" ][ "left" ];
|
||||
self.a.array[ "lean_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_lean" ][ "right" ];
|
||||
|
||||
self.a.array[ "reload" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "reload" ];
|
||||
self.a.array[ "gun_up" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "gun_up" ];
|
||||
self.a.array[ "gun_down" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "gun_down" ];
|
||||
|
||||
self.a.array[ "aim_left_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_left" ][ "left" ];
|
||||
self.a.array[ "aim_left_center" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_left" ][ "center" ];
|
||||
self.a.array[ "aim_left_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_left" ][ "right" ];
|
||||
self.a.array[ "aim_right_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_right" ][ "left" ];
|
||||
self.a.array[ "aim_right_center" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_right" ][ "center" ];
|
||||
self.a.array[ "aim_right_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "aim_right" ][ "right" ];
|
||||
self.a.array[ "add_aim_backleft_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backleft" ][ "left" ];
|
||||
self.a.array[ "add_aim_backleft_center" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backleft" ][ "center" ];
|
||||
self.a.array[ "add_aim_backleft_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backleft" ][ "right" ];
|
||||
self.a.array[ "add_aim_backright_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backright" ][ "left" ];
|
||||
self.a.array[ "add_aim_backright_center" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backright" ][ "center" ];
|
||||
self.a.array[ "add_aim_backright_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "add_aim_backright" ][ "right" ];
|
||||
self.a.array[ "straight_level_left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "straight_level" ][ "left" ];
|
||||
self.a.array[ "straight_level_center" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "straight_level" ][ "center" ];
|
||||
self.a.array[ "straight_level_right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "straight_level" ][ "right" ];
|
||||
|
||||
if ( shooting )
|
||||
{
|
||||
self.a.array["event_jump"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "drive_jump" ];
|
||||
self.a.array["event_bump"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "drive_bump" ];
|
||||
self.a.array["event_bump_big"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "drive_bump_big" ];
|
||||
self.a.array["event_sway"] = [];
|
||||
self.a.array["event_sway"][ "left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "drive_sway_left" ];
|
||||
self.a.array["event_sway"][ "right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "drive_sway_right" ];
|
||||
self.a.array["event_restore"] = %sm_aiming;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.array["event_jump"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide_jump" ];
|
||||
self.a.array["event_bump"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide_bump" ];
|
||||
self.a.array["event_bump_big"] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide_bump_big" ];
|
||||
self.a.array["event_sway"] = [];
|
||||
self.a.array["event_sway"][ "left" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide_sway_left" ];
|
||||
self.a.array["event_sway"][ "right" ] = level._scr_anim[ "snowmobile" ][ "passenger" ][ "hide_sway_right" ];
|
||||
self.a.array["event_restore"] = %sm_turn;
|
||||
}
|
||||
}
|
823
animscripts/squadmanager.gsc
Normal file
823
animscripts/squadmanager.gsc
Normal file
@ -0,0 +1,823 @@
|
||||
// squadmanager.gsc
|
||||
|
||||
/****************************************************************************
|
||||
initialization
|
||||
*****************************************************************************/
|
||||
|
||||
// initializes the squad management system
|
||||
init_squadManager()
|
||||
{
|
||||
if ( isdefined( anim.squadInitialized ) && anim.squadInitialized )
|
||||
return;
|
||||
|
||||
anim.squadCreateFuncs = [];
|
||||
anim.squadCreateStrings = [];
|
||||
|
||||
anim.squads = [];
|
||||
anim.squadIndex = [];
|
||||
anim.squadRand = 0;
|
||||
|
||||
anim.squadInitialized = true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
functionality
|
||||
*****************************************************************************/
|
||||
|
||||
createSquad( squadName, squadCreator )
|
||||
{
|
||||
assertex( !isdefined( anim.squads[ squadName ] ), "createSquad attempted to create a squad with the same name as an existing squad" );
|
||||
|
||||
//prof_begin( "createSquad" );
|
||||
|
||||
anim.squads[ squadName ] = spawnstruct();
|
||||
squad = anim.squads[ squadName ];
|
||||
squad.squadName = squadName;
|
||||
|
||||
// SRS 10/17/08: added squad.team so we can still support custom-named squads,
|
||||
// not just "axis" and "allies"
|
||||
squad.team = getSquadTeam( squadCreator );
|
||||
|
||||
squad.sightTime = 0;
|
||||
squad.origin = undefined;
|
||||
squad.forward = undefined;
|
||||
squad.enemy = undefined;
|
||||
squad.isInCombat = false;
|
||||
|
||||
squad.memberCount = 0;
|
||||
squad.members = [];
|
||||
squad.officers = [];
|
||||
squad.officerCount = 0;
|
||||
squad.squadList = [];
|
||||
|
||||
squad.memberAddFuncs = [];
|
||||
squad.memberAddStrings = [];
|
||||
squad.memberRemoveFuncs = [];
|
||||
squad.memberRemoveStrings = [];
|
||||
squad.squadUpdateFuncs = [];
|
||||
squad.squadUpdateStrings = [];
|
||||
squad.squadID = anim.squadIndex.size;
|
||||
|
||||
squad initState( "combat", 0.75 );
|
||||
squad initState( "cover", 0.75 );
|
||||
squad initState( "move", 0.75 );
|
||||
squad initState( "stop", 0.75 );
|
||||
squad initState( "death", 0.75 );
|
||||
squad initState( "suppressed", 0.75 );
|
||||
squad initState( "attacking", 0.5 );
|
||||
|
||||
// add this squad to the global index
|
||||
anim.squadIndex[ anim.squadIndex.size ] = squad;
|
||||
|
||||
squad updateSquadList();
|
||||
|
||||
// notifies for other scripts
|
||||
level notify( "squad created " + squadName );
|
||||
anim notify( "squad created " + squadName );
|
||||
|
||||
for ( i = 0; i < anim.squadCreateFuncs.size; i++ )
|
||||
{
|
||||
squadCreateFunc = anim.squadCreateFuncs[ i ];
|
||||
squad thread [[ squadCreateFunc ]]();
|
||||
}
|
||||
|
||||
// battlechatter init
|
||||
// squad animscripts\battlechatter::init_squadBattleChatter();
|
||||
|
||||
// tell all other squads to add us to their lists
|
||||
for ( i = 0; i < anim.squadIndex.size; i++ )
|
||||
anim.squadIndex[ i ] updateSquadList();
|
||||
|
||||
squad thread updateWaiter();
|
||||
squad thread squadTracker();
|
||||
squad thread officerWaiter();
|
||||
squad thread updateMemberStates();
|
||||
|
||||
//prof_end( "createSquad" );
|
||||
return( squad );
|
||||
}
|
||||
|
||||
deleteSquad( squadName )
|
||||
{
|
||||
assertex( isdefined( anim.squads[ squadName ] ), "deleteSquad attempted to delete a squad that does not exist" );
|
||||
|
||||
if ( squadName == "axis" || squadName == "team3" || squadName == "allies" )
|
||||
return;
|
||||
|
||||
squadID = anim.squads[ squadName ].squadID;
|
||||
squad = anim.squads[ squadName ];
|
||||
|
||||
squad notify( "squad_deleting" );
|
||||
|
||||
// for (i = 0; i < squad.members.size; i++)
|
||||
while ( squad.members.size )
|
||||
squad.members[ 0 ] addToSquad( squad.members[ 0 ].team );
|
||||
|
||||
anim.squadIndex[ squadID ] = anim.squadIndex[ anim.squadIndex.size - 1 ];
|
||||
anim.squadIndex[ squadID ].squadID = squadID;
|
||||
anim.squadIndex[ anim.squadIndex.size - 1 ] = undefined;
|
||||
|
||||
anim.squads[ squadName ] = undefined;
|
||||
|
||||
level notify( "squad deleted " + squadName );
|
||||
anim notify( "squad deleted " + squadName );
|
||||
|
||||
for ( i = 0; i < anim.squadIndex.size; i++ )
|
||||
anim.squadIndex[ i ] updateSquadList();
|
||||
}
|
||||
|
||||
generateSquadName()
|
||||
{
|
||||
squadName = "auto" + anim.squadRand;
|
||||
anim.squadRand++ ;
|
||||
|
||||
return( squadName );
|
||||
}
|
||||
|
||||
addPlayerToSquad( squadName )
|
||||
{
|
||||
if ( !isdefined( squadName ) )
|
||||
{
|
||||
if ( isdefined( self.script_squadname ) )
|
||||
squadName = self.script_squadname;
|
||||
else
|
||||
squadName = self.team;
|
||||
}
|
||||
|
||||
if ( !isdefined( anim.squads[ squadName ] ) )
|
||||
{
|
||||
anim createSquad( squadName, self );
|
||||
}
|
||||
|
||||
squad = anim.squads[ squadName ];
|
||||
|
||||
self.squad = squad;
|
||||
|
||||
// self.squad updateOrigin();
|
||||
}
|
||||
|
||||
// adds the ai that calls the function to the specified squad
|
||||
// if not squad is specified, the ai is added to one of the defaults
|
||||
squadChange()
|
||||
{
|
||||
self endon( "death" );
|
||||
wait( 10.0 );// ???
|
||||
|
||||
if ( !isdefined( self.script_squadname ) )
|
||||
squadName = ( self.team + self.script_flanker );
|
||||
else
|
||||
squadName = ( self.script_squadname + self.script_flanker );
|
||||
|
||||
self addToSquad( squadName );
|
||||
}
|
||||
|
||||
getSquadTeam( squadCreator )
|
||||
{
|
||||
squadTeam = "allies"; // player, allies
|
||||
if( squadCreator.team == "axis" || squadCreator.team == "neutral" || squadCreator.team == "team3" )
|
||||
{
|
||||
squadteam = squadCreator.team;
|
||||
}
|
||||
|
||||
return squadTeam;
|
||||
}
|
||||
|
||||
addToSquad( squadName )
|
||||
{
|
||||
assertex( IsSentient( self ), "addToSquad attempted to add a non-sentient member to a squad" );
|
||||
|
||||
//prof_begin( "addToSquad" );
|
||||
|
||||
if ( !isdefined( squadName ) )
|
||||
{
|
||||
if ( isdefined( self.script_flanker ) )
|
||||
self thread squadChange();
|
||||
|
||||
if ( isdefined( self.script_squadname ) )
|
||||
squadName = self.script_squadname;
|
||||
else
|
||||
squadName = self.team;
|
||||
}
|
||||
if ( !isdefined( anim.squads[ squadName ] ) )
|
||||
anim createSquad( squadName, self );
|
||||
|
||||
squad = anim.squads[ squadName ];
|
||||
|
||||
if ( isdefined( self.squad ) )
|
||||
{
|
||||
if ( self.squad == squad )
|
||||
return;
|
||||
else
|
||||
self removeFromSquad();
|
||||
}
|
||||
|
||||
// move to init.gsc
|
||||
self.lastEnemySightTime = 0;
|
||||
self.combatTime = 0;
|
||||
// end move
|
||||
|
||||
self.squad = squad;
|
||||
self.memberID = squad.members.size;
|
||||
squad.members[ self.memberID ] = self;
|
||||
squad.memberCount = squad.members.size;
|
||||
|
||||
// this is handled in wait for loadout function
|
||||
if ( isdefined( level._loadoutComplete ) )
|
||||
{
|
||||
if ( self.team == "allies" && self animscripts\battlechatter::isOfficer() )
|
||||
{
|
||||
self addOfficerToSquad();
|
||||
}
|
||||
}
|
||||
|
||||
// self.squad updateOrigin();
|
||||
|
||||
for ( i = 0; i < self.squad.memberAddFuncs.size; i++ )
|
||||
{
|
||||
memberAddFunc = self.squad.memberAddFuncs[ i ];
|
||||
self thread [[ memberAddFunc ]]( self.squad.squadName );
|
||||
}
|
||||
|
||||
//prof_end( "addToSquad" );
|
||||
|
||||
self thread memberCombatWaiter();
|
||||
self thread memberDeathWaiter();
|
||||
}
|
||||
|
||||
removeFromSquad()
|
||||
{
|
||||
//prof_begin( "removeFromSquad" );
|
||||
ASSERTEX( IsDefined( self.squad ), "removeFromSquad attempted to remove a member who was not part of a squad (self.squad == undefined)" );
|
||||
|
||||
squad = self.squad;
|
||||
memberID = -1;
|
||||
|
||||
if ( IsDefined( self ) )
|
||||
{
|
||||
memberID = self.memberID;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < squad.members.size; i++ )
|
||||
{
|
||||
if ( squad.members[ i ] == self )
|
||||
memberID = i;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERTEX( memberID > - 1, "removeFromSquad could not find memberID" );
|
||||
|
||||
if ( memberID != squad.members.size - 1 )
|
||||
{
|
||||
other = squad.members[ squad.members.size - 1 ];
|
||||
squad.members[ memberID ] = other;
|
||||
if ( isdefined( other ) )
|
||||
other.memberID = memberID;
|
||||
}
|
||||
|
||||
squad.members[ squad.members.size - 1 ] = undefined;
|
||||
squad.memberCount = squad.members.size;
|
||||
|
||||
if ( IsDefined( self.officerID ) )
|
||||
{
|
||||
self removeOfficerFromSquad();
|
||||
}
|
||||
|
||||
for ( i = 0; i < self.squad.memberRemoveFuncs.size; i++ )
|
||||
{
|
||||
memberRemoveFunc = self.squad.memberRemoveFuncs[ i ];
|
||||
self thread [[ memberRemoveFunc ]]( squad.squadName );
|
||||
}
|
||||
|
||||
assert( squad.members.size == squad.memberCount );
|
||||
|
||||
if ( squad.memberCount == 0 )
|
||||
{
|
||||
deleteSquad( squad.squadName );
|
||||
}
|
||||
|
||||
if ( isdefined( self ) )
|
||||
{
|
||||
self.squad = undefined;
|
||||
self.memberID = undefined;
|
||||
}
|
||||
|
||||
self notify( "removed from squad" );
|
||||
|
||||
//prof_end( "removeFromSquad" );
|
||||
}
|
||||
|
||||
addOfficerToSquad()
|
||||
{
|
||||
squad = self.squad;
|
||||
|
||||
if ( isdefined( self.officerID ) )
|
||||
return;
|
||||
|
||||
assertex( !isdefined( self.officerID ), "addOfficerToSquad attempted to add a member that is already in an officers" );
|
||||
|
||||
self.officerID = squad.officers.size;
|
||||
squad.officers[ self.officerID ] = self;
|
||||
squad.officerCount = squad.officers.size;
|
||||
}
|
||||
|
||||
removeOfficerFromSquad()
|
||||
{
|
||||
//prof_begin( "removeOfficerFromSquad" );
|
||||
|
||||
squad = self.squad;
|
||||
officerID = -1;
|
||||
|
||||
if ( isdefined( self ) )
|
||||
{
|
||||
officerID = self.officerID;
|
||||
}
|
||||
else
|
||||
{
|
||||
for ( i = 0; i < squad.officers.size; i++ )
|
||||
{
|
||||
if ( squad.officers[ i ] == self )
|
||||
officerID = i;
|
||||
}
|
||||
}
|
||||
|
||||
assertex( officerID > - 1, "removeOfficerFromSquad could not find officerID" );
|
||||
|
||||
if ( officerID != squad.officers.size - 1 )
|
||||
{
|
||||
other = squad.officers[ squad.officers.size - 1 ];
|
||||
squad.officers[ officerID ] = other;
|
||||
if ( isdefined( other ) )
|
||||
other.officerID = officerID;
|
||||
}
|
||||
|
||||
squad.officers[ squad.officers.size - 1 ] = undefined;
|
||||
squad.officerCount = squad.officers.size;
|
||||
|
||||
assert( squad.officers.size == squad.officerCount );
|
||||
|
||||
if ( isdefined( self ) )
|
||||
self.officerID = undefined;
|
||||
|
||||
//prof_end( "removeOfficerFromSquad" );
|
||||
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
trackers/waiters
|
||||
*****************************************************************************/
|
||||
|
||||
officerWaiter()
|
||||
{
|
||||
if ( !isdefined( level._loadoutComplete ) )
|
||||
{
|
||||
anim waittill( "loadout complete" );
|
||||
}
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( self.members[ i ] animscripts\battlechatter::isOfficer() )
|
||||
{
|
||||
self.members[ i ] addOfficerToSquad();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateWaiter()
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
anim waittill( "squadupdate", action );
|
||||
|
||||
//prof_begin( "updateWaiter" );
|
||||
|
||||
switch( action )
|
||||
{
|
||||
case "squadlist":
|
||||
self updateSquadList();
|
||||
break;
|
||||
case "combat":
|
||||
self updateCombat();
|
||||
break;
|
||||
case "origin":
|
||||
self updateOrigin();
|
||||
break;
|
||||
case "forward":
|
||||
self updateHeading();
|
||||
break;
|
||||
}
|
||||
|
||||
//prof_end( "updateWaiter" );
|
||||
}
|
||||
}
|
||||
|
||||
squadTracker()
|
||||
{
|
||||
anim endon( "squad deleted " + self.squadName );
|
||||
// even with the long wait time, this is a crappy way to track things
|
||||
// ideally the updateFunctions would only be called when another function needs to know the status of something
|
||||
// rather than polling like it's doing now.
|
||||
while ( 1 )
|
||||
{
|
||||
// combat can be removed
|
||||
self updateAll();
|
||||
|
||||
wait( 0.1 );
|
||||
}
|
||||
}
|
||||
|
||||
memberDeathWaiter()
|
||||
{
|
||||
// self notify ("squad change");
|
||||
self endon( "removed from squad" );
|
||||
|
||||
self waittill( "death", attacker );
|
||||
|
||||
if ( isdefined( self ) )
|
||||
{
|
||||
self.attacker = attacker;
|
||||
}
|
||||
|
||||
self removeFromSquad();
|
||||
}
|
||||
|
||||
memberCombatWaiter()
|
||||
{
|
||||
// self notify ("squad change");
|
||||
self endon( "removed from squad" );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self waittill( "enemy" );
|
||||
|
||||
if ( !isdefined( self.enemy ) )
|
||||
self.squad notify( "squadupdate", "combat" );
|
||||
else
|
||||
self.squad.isInCombat = true;
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
utility
|
||||
*****************************************************************************/
|
||||
|
||||
updateHeading()
|
||||
{
|
||||
if ( isdefined( self.enemy ) )
|
||||
{
|
||||
self.forward = vectornormalize( self.enemy.origin - self.origin );
|
||||
return;
|
||||
}
|
||||
|
||||
newHeading = ( 0, 0, 0 );
|
||||
numInfluences = 0;
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( !isalive( self.members[ i ] ) )
|
||||
continue;
|
||||
// logic here to prune out separated members... otherwise origin could be too vague
|
||||
newHeading += anglestoforward( self.members[ i ].angles );
|
||||
numInfluences++ ;
|
||||
}
|
||||
|
||||
if ( numInfluences )
|
||||
self.forward = ( newHeading[ 0 ] / numInfluences, newHeading[ 1 ] / numInfluences, newHeading[ 2 ] / numInfluences );
|
||||
else
|
||||
self.forward = newHeading;
|
||||
}
|
||||
|
||||
updateOrigin()
|
||||
{
|
||||
//prof_begin( "updateOrigin" );
|
||||
newOrigin = ( 0, 0, 0 );
|
||||
numInfluences = 0;
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
// logic here to prune out separated members... otherwise origin could be too vague
|
||||
|
||||
// assertex (isdefined (self.members[i]), "updateOrigin run while a squad member was undefined");
|
||||
if ( !isalive( self.members[ i ] ) )
|
||||
continue;
|
||||
|
||||
newOrigin += self.members[ i ].origin;
|
||||
numInfluences++ ;
|
||||
}
|
||||
|
||||
if ( numInfluences )
|
||||
self.origin = ( newOrigin[ 0 ] / numInfluences, newOrigin[ 1 ] / numInfluences, newOrigin[ 2 ] / numInfluences );
|
||||
else
|
||||
self.origin = newOrigin;
|
||||
|
||||
//prof_end( "updateOrigin" );
|
||||
}
|
||||
|
||||
updateCombat()
|
||||
{
|
||||
//prof_begin( "updateCombat" );
|
||||
|
||||
self.isInCombat = false;
|
||||
|
||||
// reset squad contact status
|
||||
for ( i = 0; i < anim.squadIndex.size; i++ )
|
||||
self.squadList[ anim.squadIndex[ i ].squadName ].isInContact = false;
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( isdefined( self.members[ i ].enemy ) && isdefined( self.members[ i ].enemy.squad ) && self.members[ i ].combatTime > 0 )
|
||||
self.squadList[ self.members[ i ].enemy.squad.squadName ].isInContact = true;
|
||||
}
|
||||
|
||||
//prof_end( "updateCombat" );
|
||||
}
|
||||
|
||||
updateEnemy()
|
||||
{
|
||||
//prof_begin( "updateEnemy" );
|
||||
curEnemy = undefined;
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( isdefined( self.members[ i ].enemy ) && isdefined( self.members[ i ].enemy.squad ) )
|
||||
{
|
||||
if ( !isdefined( curEnemy ) )
|
||||
curEnemy = self.members[ i ].enemy.squad;
|
||||
else if ( self.members[ i ].enemy.squad.memberCount > curEnemy.memberCount )
|
||||
curEnemy = self.members[ i ].enemy.squad;
|
||||
}
|
||||
}
|
||||
|
||||
self.enemy = curEnemy;
|
||||
//prof_end( "updateEnemy" );
|
||||
}
|
||||
|
||||
updateAll()
|
||||
{
|
||||
//prof_begin( "updateAll" );
|
||||
|
||||
newOrigin = ( 0, 0, 0 );
|
||||
numInfluences = 0;
|
||||
curEnemy = undefined;
|
||||
isInCombat = false;
|
||||
|
||||
self updateCombat();
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( !isalive( self.members[ i ] ) )
|
||||
continue;
|
||||
|
||||
// logic here to prune out separated members... otherwise origin could be too vague
|
||||
newOrigin += self.members[ i ].origin;
|
||||
numInfluences++ ;
|
||||
|
||||
if ( isdefined( self.members[ i ].enemy ) && isdefined( self.members[ i ].enemy.squad ) )
|
||||
{
|
||||
if ( !isdefined( curEnemy ) )
|
||||
curEnemy = self.members[ i ].enemy.squad;
|
||||
else if ( self.members[ i ].enemy.squad.memberCount > curEnemy.memberCount )
|
||||
curEnemy = self.members[ i ].enemy.squad;
|
||||
}
|
||||
}
|
||||
|
||||
if ( numInfluences )
|
||||
self.origin = ( newOrigin[ 0 ] / numInfluences, newOrigin[ 1 ] / numInfluences, newOrigin[ 2 ] / numInfluences );
|
||||
else
|
||||
self.origin = newOrigin;
|
||||
|
||||
self.isInCombat = isInCombat;
|
||||
self.enemy = curEnemy;
|
||||
|
||||
// integreate this at some point
|
||||
self updateHeading();
|
||||
|
||||
//prof_end( "updateAll" );
|
||||
}
|
||||
|
||||
updateSquadList()
|
||||
{
|
||||
//prof_begin( "updateSquadList" );
|
||||
|
||||
for ( i = 0; i < anim.squadIndex.size; i++ )
|
||||
{
|
||||
if ( !isdefined( self.squadList[ anim.squadIndex[ i ].squadName ] ) )
|
||||
{
|
||||
self.squadList[ anim.squadIndex[ i ].squadName ] = spawnstruct();
|
||||
self.squadList[ anim.squadIndex[ i ].squadName ].isInContact = false;
|
||||
}
|
||||
|
||||
for ( j = 0; j < self.squadUpdateFuncs.size; j++ )
|
||||
{
|
||||
squadUpdateFunc = self.squadUpdateFuncs[ j ];
|
||||
self thread [[ squadUpdateFunc ]]( anim.squadIndex[ i ].squadName );
|
||||
}
|
||||
}
|
||||
|
||||
//prof_end( "updateSquadList" );
|
||||
}
|
||||
|
||||
printAboveHead( string, duration, offset, color )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( !isdefined( offset ) )
|
||||
offset = ( 0, 0, 0 );
|
||||
if ( !isdefined( color ) )
|
||||
color = ( 1, 0, 0 );
|
||||
|
||||
for ( i = 0; i < ( duration * 2 ); i++ )
|
||||
{
|
||||
if ( !isalive( self ) )
|
||||
return;
|
||||
|
||||
aboveHead = self getshootatpos() + ( 0, 0, 10 ) + offset;
|
||||
print3d( aboveHead, string, color, 1, 0.5 ); // origin, text, RGB, alpha, scale
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
ai functions
|
||||
*****************************************************************************/
|
||||
|
||||
aiUpdateAnimState( animscript )
|
||||
{
|
||||
//prof_begin( "aiUpdateAnimState" );
|
||||
|
||||
switch( animscript )
|
||||
{
|
||||
case "combat":
|
||||
case "move":
|
||||
case "stop":
|
||||
case "death":
|
||||
self.a.state = animscript;
|
||||
break;
|
||||
|
||||
case "pain":
|
||||
case "grenadecower":
|
||||
break;
|
||||
|
||||
case "cover_crouch":
|
||||
case "cover_left":
|
||||
case "cover_prone":
|
||||
case "cover_right":
|
||||
case "cover_stand":
|
||||
case "cover_wide_left":
|
||||
case "cover_wide_right":
|
||||
case "concealment_crouch":
|
||||
case "concealment_prone":
|
||||
case "concealment_stand":
|
||||
case "stalingrad_cover_crouch":
|
||||
self.a.state = "cover";
|
||||
break;
|
||||
|
||||
case "aim":
|
||||
case "l33t truckride combat":
|
||||
self.a.state = "combat";
|
||||
break;
|
||||
}
|
||||
|
||||
//prof_end( "aiUpdateAnimState" );
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
squad functions
|
||||
*****************************************************************************/
|
||||
|
||||
updateStates()
|
||||
{
|
||||
self resetState( "combat" );
|
||||
self resetState( "cover" );
|
||||
self resetState( "move" );
|
||||
self resetState( "stop" );
|
||||
self resetState( "death" );
|
||||
self resetState( "suppressed" );
|
||||
self resetState( "attacking" );
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( !isalive( self.members[ i ] ) )
|
||||
continue;
|
||||
|
||||
self queryMemberAnimState( self.members[ i ] );
|
||||
self queryMemberState( self.members[ i ], "suppressed" );
|
||||
self queryMemberState( self.members[ i ], "combat" );
|
||||
self queryMemberState( self.members[ i ], "attacking" );
|
||||
self queryMemberState( self.members[ i ], "cover" );
|
||||
}
|
||||
}
|
||||
|
||||
updateMemberStates()
|
||||
{
|
||||
anim endon( "squad deleted " + self.squadName );
|
||||
|
||||
timeSlice = 0.05;
|
||||
while ( 1 )
|
||||
{
|
||||
//prof_begin( "updateMemberStates" );
|
||||
|
||||
for ( i = 0; i < self.members.size; i++ )
|
||||
{
|
||||
if ( !isalive( self.members[ i ] ) )
|
||||
continue;
|
||||
|
||||
self.members[ i ] aiUpdateCombat( timeSlice );
|
||||
self.members[ i ] aiUpdateSuppressed( timeSlice );
|
||||
}
|
||||
|
||||
//prof_end( "updateMemberStates" );
|
||||
wait( timeSlice );
|
||||
}
|
||||
}
|
||||
|
||||
aiUpdateCombat( timeSlice )
|
||||
{
|
||||
if ( isdefined( self.lastEnemySightPos ) )
|
||||
{
|
||||
if ( self.combatTime < 0 )
|
||||
self.combatTime = timeSlice;
|
||||
else
|
||||
self.combatTime += timeSlice;
|
||||
|
||||
self.lastEnemySightTime = gettime();
|
||||
return;
|
||||
}
|
||||
else if ( self issuppressed() )
|
||||
{
|
||||
self.combatTime += timeSlice;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self.combatTime > 0 )
|
||||
self.combatTime = ( 0 - timeSlice );
|
||||
else
|
||||
self.combatTime -= timeSlice;
|
||||
}
|
||||
|
||||
aiUpdateSuppressed( timeSlice )
|
||||
{
|
||||
if ( self.suppressed )
|
||||
{
|
||||
if ( self.suppressedTime < 0 )
|
||||
self.suppressedTime = timeSlice;
|
||||
else
|
||||
self.suppressedTime += timeSlice;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ( self.suppressedTime > 0 )
|
||||
self.suppressedTime = ( 0 - timeSlice );
|
||||
else
|
||||
self.suppressedTime -= timeSlice;
|
||||
}
|
||||
|
||||
initState( state, activateRatio )
|
||||
{
|
||||
self.squadStates[ state ] = spawnstruct();
|
||||
self.squadStates[ state ].activateRatio = activateRatio;
|
||||
self.squadStates[ state ].isActive = false;
|
||||
self.squadStates[ state ].numActive = 0;
|
||||
}
|
||||
|
||||
resetState( state )
|
||||
{
|
||||
self.squadStates[ state ].isActive = false;
|
||||
self.squadStates[ state ].numActive = 0;
|
||||
}
|
||||
|
||||
queryMemberAnimState( member )
|
||||
{
|
||||
self.squadStates[ member.a.state ].numActive++ ;
|
||||
if ( self.squadStates[ member.a.state ].numActive > ( self.squadStates[ member.a.state ].activateRatio * self.members.size ) )
|
||||
self.squadStates[ member.a.state ].isActive = true;
|
||||
}
|
||||
|
||||
queryMemberState( member, state )
|
||||
{
|
||||
//prof_begin( "queryMemberState" );
|
||||
switch( state )
|
||||
{
|
||||
case "suppressed":
|
||||
if ( member.suppressedTime > 1.0 )
|
||||
self.squadStates[ state ].numActive++ ;
|
||||
break;
|
||||
case "combat":
|
||||
if ( member.combatTime > 0.0 )
|
||||
self.squadStates[ state ].numActive++ ;
|
||||
break;
|
||||
case "attacking":
|
||||
if ( gettime() < member.a.lastShootTime + 2000 )
|
||||
self.squadStates[ state ].numActive++ ;
|
||||
break;
|
||||
case "cover":
|
||||
if ( !member animscripts\battlechatter::isExposed() )
|
||||
self.squadStates[ state ].numActive++ ;
|
||||
break;
|
||||
}
|
||||
if ( self.squadStates[ state ].numActive > ( self.squadStates[ state ].activateRatio * self.members.size ) )
|
||||
self.squadStates[ state ].isActive = true;
|
||||
//prof_end( "queryMemberState" );
|
||||
}
|
281
animscripts/stop.gsc
Normal file
281
animscripts/stop.gsc
Normal file
@ -0,0 +1,281 @@
|
||||
// "Stop" makes the character not walk, run or fight. He can be standing, crouching or lying
|
||||
// prone; he can be alert or idle.
|
||||
|
||||
#include animscripts\combat_utility;
|
||||
#include animscripts\Utility;
|
||||
#include animscripts\SetPoseMovement;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( isdefined( self.no_ai ) )
|
||||
return;
|
||||
|
||||
if ( isdefined( self.locked_combat ) )
|
||||
{
|
||||
animscripts\locked_combat::locked_combat();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( isdefined( self.onSnowMobile ) )
|
||||
{
|
||||
animscripts\snowmobile::main();
|
||||
return;
|
||||
}
|
||||
|
||||
self notify( "stopScript" );
|
||||
self endon( "killanimscript" );
|
||||
/#
|
||||
if ( getdebugdvar( "anim_preview" ) != "" )
|
||||
return;
|
||||
#/
|
||||
|
||||
[[ self.exception[ "stop_immediate" ] ]]();
|
||||
// We do the exception_stop script a little late so that the AI has some animation they're playing
|
||||
// otherwise they'd go into basepose.
|
||||
thread delayedException();
|
||||
|
||||
animscripts\utility::initialize( "stop" );
|
||||
|
||||
specialIdleLoop();
|
||||
|
||||
self randomizeIdleSet();
|
||||
|
||||
self thread setLastStoppedTime();
|
||||
self thread animscripts\reactions::reactionsCheckLoop();
|
||||
|
||||
transitionedToIdle = isdefined( self.customIdleAnimSet );
|
||||
if ( !transitionedToIdle )
|
||||
{
|
||||
if ( self.a.weaponPos[ "right" ] == "none" && self.a.weaponPos[ "left" ] == "none" )
|
||||
transitionedToIdle = true;
|
||||
else if ( AngleClamp180( self getMuzzleAngle()[ 0 ] ) > 20 )
|
||||
transitionedToIdle = true;
|
||||
}
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
desiredPose = getDesiredIdlePose();
|
||||
|
||||
if ( desiredPose == "prone" )
|
||||
{
|
||||
transitionedToIdle = true;
|
||||
self ProneStill();
|
||||
}
|
||||
else
|
||||
{
|
||||
assertex( desiredPose == "crouch" || desiredPose == "stand", desiredPose );
|
||||
|
||||
if ( self.a.pose != desiredPose )
|
||||
{
|
||||
self clearAnim( %root, 0.3 );
|
||||
transitionedToIdle = false;
|
||||
}
|
||||
self SetPoseMovement( desiredPose, "stop" );
|
||||
|
||||
if ( !transitionedToIdle )
|
||||
{
|
||||
self transitionToIdle( desiredPose, self.a.idleSet );
|
||||
transitionedToIdle = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
self playIdle( desiredPose, self.a.idleSet );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setLastStoppedTime()
|
||||
{
|
||||
self endon( "death" );
|
||||
self waittill( "killanimscript" );
|
||||
self.lastStoppedTime = gettime();
|
||||
}
|
||||
|
||||
specialIdleLoop()
|
||||
{
|
||||
self endon( "stop_specialidle" );
|
||||
|
||||
if ( isdefined( self.specialIdleAnim ) )
|
||||
{
|
||||
idleAnimArray = self.specialIdleAnim;
|
||||
self.specialIdleAnim = undefined;
|
||||
self notify( "clearing_specialIdleAnim" );
|
||||
|
||||
self animmode( "gravity" );
|
||||
self orientmode( "face current" );
|
||||
|
||||
self clearAnim( %root, .2 );
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
self setflaggedanimrestart( "special_idle", idleAnimArray[ randomint( idleAnimArray.size ) ], 1, 0.2, 1 );
|
||||
self waittillmatch( "special_idle", "end" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getDesiredIdlePose()
|
||||
{
|
||||
myNode = animscripts\utility::GetClaimedNode();
|
||||
if ( isDefined( myNode ) )
|
||||
{
|
||||
myNodeAngle = myNode.angles[ 1 ];
|
||||
myNodeType = myNode.type;
|
||||
}
|
||||
else
|
||||
{
|
||||
myNodeAngle = self.desiredAngle;
|
||||
myNodeType = "node was undefined";
|
||||
}
|
||||
|
||||
self animscripts\face::SetIdleFace( anim.alertface );
|
||||
|
||||
// Find out if we should be standing, crouched or prone
|
||||
desiredPose = animscripts\utility::choosePose();
|
||||
|
||||
if ( myNodeType == "Cover Stand" || myNodeType == "Conceal Stand" )
|
||||
{
|
||||
// At cover_stand nodes, we don't want to crouch since it'll most likely make our gun go through the wall.
|
||||
desiredPose = animscripts\utility::choosePose( "stand" );
|
||||
}
|
||||
else if ( myNodeType == "Cover Crouch" || myNodeType == "Conceal Crouch" )
|
||||
{
|
||||
// We should crouch at concealment crouch nodes.
|
||||
desiredPose = animscripts\utility::choosePose( "crouch" );
|
||||
}
|
||||
else if ( myNodeType == "Cover Prone" || myNodeType == "Conceal Prone" )
|
||||
{
|
||||
// We should go prone at prone nodes.
|
||||
desiredPose = animscripts\utility::choosePose( "prone" );
|
||||
}
|
||||
|
||||
return desiredPose;
|
||||
}
|
||||
|
||||
transitionToIdle( pose, idleSet )
|
||||
{
|
||||
if ( self isCQBWalking() && self.a.pose == "stand" )
|
||||
pose = "stand_cqb";
|
||||
|
||||
if ( isdefined( anim.idleAnimTransition[ pose ] ) )
|
||||
{
|
||||
assert( isdefined( anim.idleAnimTransition[ pose ][ "in" ] ) );
|
||||
|
||||
// idles and transitions should have no tag origin movement
|
||||
//self animmode( "zonly_physics", false );
|
||||
idleAnim = anim.idleAnimTransition[ pose ][ "in" ];
|
||||
self setFlaggedAnimKnobAllRestart( "idle_transition", idleAnim, %body, 1, .2, self.animplaybackrate );
|
||||
self animscripts\shared::DoNoteTracks( "idle_transition" );
|
||||
//self animmode( "normal", false );
|
||||
}
|
||||
}
|
||||
|
||||
playIdle( pose, idleSet )
|
||||
{
|
||||
if ( self isCQBWalking() && self.a.pose == "stand" )
|
||||
pose = "stand_cqb";
|
||||
|
||||
idleAddAnim = undefined;
|
||||
|
||||
if ( isdefined( self.customIdleAnimSet ) && isdefined( self.customIdleAnimSet[ pose ] ) )
|
||||
{
|
||||
idleAnim = self.customIdleAnimSet[ pose ];
|
||||
|
||||
additive = pose + "_add";
|
||||
if ( isdefined( self.customIdleAnimSet[ additive ] ) )
|
||||
idleAddAnim = self.customIdleAnimSet[ additive ];
|
||||
}
|
||||
else
|
||||
{
|
||||
idleSet = idleSet % anim.idleAnimArray[ pose ].size;
|
||||
|
||||
idleAnim = anim_array( anim.idleAnimArray[ pose ][ idleSet ], anim.idleAnimWeights[ pose ][ idleSet ] );
|
||||
}
|
||||
|
||||
transTime = 0.2;
|
||||
if ( gettime() == self.a.scriptStartTime )
|
||||
transTime = 0.5;
|
||||
|
||||
if ( isdefined( idleAddAnim ) )
|
||||
{
|
||||
self setAnimKnobAll( idleAnim, %body, 1, transTime, 1 );
|
||||
self setAnim( %add_idle );
|
||||
self setFlaggedAnimKnobAllRestart( "idle", idleAddAnim, %add_idle, 1, transTime, self.animplaybackrate );
|
||||
}
|
||||
else
|
||||
{
|
||||
self setFlaggedAnimKnobAllRestart( "idle", idleAnim, %body, 1, transTime, self.animplaybackrate );
|
||||
}
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "idle" );
|
||||
}
|
||||
|
||||
ProneStill()
|
||||
{
|
||||
if ( self.a.pose != "prone" )
|
||||
{
|
||||
anim_array[ "stand_2_prone" ] = %stand_2_prone;
|
||||
anim_array[ "crouch_2_prone" ] = %crouch_2_prone;
|
||||
|
||||
transAnim = anim_array[ self.a.pose + "_2_prone" ];
|
||||
assertex( isdefined( transAnim ), self.a.pose );
|
||||
assert( animHasNotetrack( transAnim, "anim_pose = \"prone\"" ) );
|
||||
|
||||
self setFlaggedAnimKnobAllRestart( "trans", transAnim, %body, 1, .2, 1.0 );
|
||||
animscripts\shared::DoNoteTracks( "trans" );
|
||||
|
||||
assert( self.a.pose == "prone" );
|
||||
self.a.movement = "stop";
|
||||
|
||||
self setProneAnimNodes( -45, 45, %prone_legs_down, %exposed_modern, %prone_legs_up );
|
||||
|
||||
return;// in case we need to change our pose again for whatever reason
|
||||
}
|
||||
|
||||
self thread UpdateProneThread();
|
||||
|
||||
if ( randomint( 10 ) < 3 )
|
||||
{
|
||||
twitches = [];
|
||||
twitches[ 0 ] = %prone_twitch_ammocheck;
|
||||
twitches[ 1 ] = %prone_twitch_look;
|
||||
twitches[ 2 ] = %prone_twitch_scan;
|
||||
twitches[ 3 ] = %prone_twitch_lookfast;
|
||||
twitches[ 4 ] = %prone_twitch_lookup;
|
||||
|
||||
//twitches[ 1 ] = %prone_twitch_ammocheck2;
|
||||
//twitches[ 6 ] = %prone_twitch_scan2;
|
||||
|
||||
twitchAnim = twitches[ randomint( twitches.size ) ];
|
||||
self setFlaggedAnimKnobAll( "prone_idle", twitchAnim, %exposed_modern, 1, 0.2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
self setAnimKnobAll( %prone_aim_5, %exposed_modern, 1, 0.2 );
|
||||
self setFlaggedAnimKnob( "prone_idle", %prone_idle, 1, 0.2 );// ( additive idle on top )
|
||||
}
|
||||
self waittillmatch( "prone_idle", "end" );
|
||||
|
||||
self notify( "kill UpdateProneThread" );
|
||||
}
|
||||
|
||||
UpdateProneThread()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self endon( "kill UpdateProneThread" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self animscripts\cover_prone::UpdateProneWrapper( 0.1 );
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
delayedException()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
wait( 0.05 );
|
||||
[[ self.exception[ "stop" ] ]]();
|
||||
}
|
48
animscripts/technical/stand.gsc
Normal file
48
animscripts/technical/stand.gsc
Normal file
@ -0,0 +1,48 @@
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// It'd be nice if I had an animation to get to stand without moving...
|
||||
self.a.movement = "stop";
|
||||
|
||||
turret = self getTurret();
|
||||
turret thread turretInit( self );
|
||||
|
||||
self.primaryTurretAnim = %technicalGunner_aim;
|
||||
self.additiveTurretIdle = %technical_turret_driveidle;
|
||||
self.additiveTurretFire = %technical_turret_firing;
|
||||
|
||||
self.painFunction = ::technical_pain;
|
||||
self.deathAnim = %technical_turret_death;
|
||||
|
||||
thread animscripts\saw\common::main( turret );
|
||||
}
|
||||
|
||||
technical_pain()
|
||||
{
|
||||
self setFlaggedAnimKnobAllRestart( "painanim", %technical_turret_pain, %body, 1, .1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "painanim" );
|
||||
}
|
||||
|
||||
//=====================================
|
||||
#using_animtree( "mg42" );
|
||||
|
||||
turretInit( owner )
|
||||
{
|
||||
self.leftArc = 180;
|
||||
self.rightArc = 180;
|
||||
|
||||
self UseAnimTree( #animtree );
|
||||
|
||||
self.additiveTurretIdle = %saw_gunner_idle_mg;
|
||||
self.additiveTurretFire = %saw_gunner_firing_mg_add;
|
||||
|
||||
self endon( "death" );
|
||||
owner waittill( "killanimscript" );// code
|
||||
|
||||
self stopUseAnimTree();
|
||||
}
|
27
animscripts/traverse/crouch_jump_down_40.gsc
Normal file
27
animscripts/traverse/crouch_jump_down_40.gsc
Normal file
@ -0,0 +1,27 @@
|
||||
// crouch_jump_down_40.gsc
|
||||
// Makes the character roll down off a ledge at no higher than 32 units. Designed for 40 units but should work for 44-70 or so.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self.a.movement = "walk";
|
||||
self traverseMode( "nogravity" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
//crouch_jump_down_40
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "stepanim", %jump_across_72, %body, 1, .1, 1 );
|
||||
wait .15;
|
||||
// self waittillmatch("stepanim", "gravity on");
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "stepanim" );
|
||||
}
|
25
animscripts/traverse/duck_under_56.gsc
Normal file
25
animscripts/traverse/duck_under_56.gsc
Normal file
@ -0,0 +1,25 @@
|
||||
// Jump_across_72.gsc
|
||||
// Makes the character do a lateral jump of 72 units.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "jumpanim", %gulag_pipe_traverse, %body, 1, .1, 1 );
|
||||
self waittillmatch( "jumpanim", "finish" );
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "jumpanim" );
|
||||
}
|
27
animscripts/traverse/fence_climb.gsc
Normal file
27
animscripts/traverse/fence_climb.gsc
Normal file
@ -0,0 +1,27 @@
|
||||
// Fence_climb.gsc
|
||||
// Makes the character climb a 48 unit fence
|
||||
// TEMP - copied wall dive until we get an animation
|
||||
// Makes the character dive over a low wall
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );// So he doesn't get stuck if the wall is a little too high
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "diveanim", %fenceclimb, %body, 1, .1, 1 );
|
||||
// self waittillmatch("diveanim", "gravity on");
|
||||
self animscripts\shared::DoNoteTracks( "diveanim" );
|
||||
self traverseMode( "gravity" );
|
||||
}
|
30
animscripts/traverse/jump_across_100.gsc
Normal file
30
animscripts/traverse/jump_across_100.gsc
Normal file
@ -0,0 +1,30 @@
|
||||
// Jump_across_100.gsc
|
||||
// Makes the character do a lateral jump of 100 units.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
jumpAnims = [];
|
||||
jumpAnims[0] = %jump_across_100_spring;
|
||||
jumpAnims[1] = %jump_across_100_lunge;
|
||||
jumpAnims[2] = %jump_across_100_stumble;
|
||||
|
||||
jumpanim = jumpAnims[ randomint( jumpAnims.size ) ];
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "jumpanim", jumpanim, %body, 1, .1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "jumpanim" );
|
||||
}
|
25
animscripts/traverse/jump_across_72.gsc
Normal file
25
animscripts/traverse/jump_across_72.gsc
Normal file
@ -0,0 +1,25 @@
|
||||
// Jump_across_72.gsc
|
||||
// Makes the character do a lateral jump of 72 units.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "jumpanim", %jump_across_72, %body, 1, .1, 1 );
|
||||
self waittillmatch( "jumpanim", "gravity on" );
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "jumpanim" );
|
||||
}
|
32
animscripts/traverse/jump_over_high_wall.gsc
Normal file
32
animscripts/traverse/jump_over_high_wall.gsc
Normal file
@ -0,0 +1,32 @@
|
||||
// Jump_over_high_wall.gsc
|
||||
// Makes the character dive over a high wall. Designed for getting bad guys into levels - it looks bad from the back.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self clearanim( %stand_and_crouch, 0.1 );
|
||||
self setFlaggedAnimKnoballRestart( "diveanim", %jump_over_high_wall, %body, 1, .1, 1 );
|
||||
self playsound( "dive_wall" );
|
||||
self waittillmatch( "diveanim", "gravity on" );
|
||||
self traverseMode( "nogravity" );
|
||||
self waittillmatch( "diveanim", "noclip" );
|
||||
self traverseMode( "noclip" );
|
||||
self waittillmatch( "diveanim", "gravity on" );
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "diveanim" );
|
||||
}
|
||||
|
25
animscripts/traverse/jump_up_80.gsc
Normal file
25
animscripts/traverse/jump_up_80.gsc
Normal file
@ -0,0 +1,25 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "dog" );
|
||||
main()
|
||||
{
|
||||
assertex( self.type == "dog", "Only dogs can do this traverse currently." );
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
realHeight = startnode.traverse_height - startnode.origin[ 2 ];
|
||||
self thread teleportThread( realHeight - 80 );
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
self setflaggedanimrestart( "jump_up_80", anim.dogTraverseAnims[ "jump_up_80" ], 1, 0.2, 1 );
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "jump_up_80" );
|
||||
|
||||
self.traverseComplete = true;
|
||||
}
|
19
animscripts/traverse/jumpdown_130.gsc
Normal file
19
animscripts/traverse/jumpdown_130.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 7, 0.7 );
|
||||
else
|
||||
jumpdown_130_human();
|
||||
}
|
||||
|
||||
jumpdown_130_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %traverse_jumpdown_130;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
19
animscripts/traverse/jumpdown_40.gsc
Normal file
19
animscripts/traverse/jumpdown_40.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 3, 1.0 );
|
||||
else
|
||||
low_wall_human();
|
||||
}
|
||||
|
||||
low_wall_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %traverse_jumpdown_40;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
19
animscripts/traverse/jumpdown_56.gsc
Normal file
19
animscripts/traverse/jumpdown_56.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 5, 1.0 );
|
||||
else
|
||||
low_wall_human();
|
||||
}
|
||||
|
||||
low_wall_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %traverse_jumpdown_56;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
19
animscripts/traverse/jumpdown_96.gsc
Normal file
19
animscripts/traverse/jumpdown_96.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 7, 0.8 );
|
||||
else
|
||||
low_wall_human();
|
||||
}
|
||||
|
||||
low_wall_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %traverse_jumpdown_96;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
44
animscripts/traverse/ladder_down.gsc
Normal file
44
animscripts/traverse/ladder_down.gsc
Normal file
@ -0,0 +1,44 @@
|
||||
// ladder_down.gsc
|
||||
// Climbs down a ladder of any height by using a looping animation.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// First, get on
|
||||
endnode = self getnegotiationendnode();
|
||||
assert( isdefined( endnode ) );
|
||||
endPos = endnode.origin;
|
||||
//("ladder_down: about to start climbing. Height to climb: " + (endPos[2] - self.origin[2]) );#/
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "climbanim", %ladder_climbon, %body, 1, .1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "climbanim" );
|
||||
|
||||
// Now do the cycle
|
||||
climbAnim = %ladder_climbdown;
|
||||
self setFlaggedAnimKnoballRestart( "climbanim", climbAnim, %body, 1, .1, 1 );
|
||||
|
||||
cycleDelta = GetMoveDelta( climbAnim, 0, 1 );
|
||||
climbRate = cycleDelta[ 2 ] / getanimlength( climbAnim );
|
||||
climbingTime = ( endPos[ 2 ] - self.origin[ 2 ] ) / climbRate;
|
||||
|
||||
self animscripts\shared::DoNoteTracksForTime( climbingTime, "climbanim" );
|
||||
|
||||
self traverseMode( "gravity" );
|
||||
self.a.movement = "stop";
|
||||
self.a.pose = "stand";
|
||||
//("ladder_down: all done");#/
|
||||
}
|
51
animscripts/traverse/ladder_up.gsc
Normal file
51
animscripts/traverse/ladder_up.gsc
Normal file
@ -0,0 +1,51 @@
|
||||
// ladder_up.gsc
|
||||
// Climbs a ladder of any height by using a looping animation, and gets off at the top.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
// self traverseMode("nogravity");
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
climbAnim = %ladder_climbup;
|
||||
endAnim = %ladder_climboff;
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "climbanim", climbAnim, %body, 1, .1, 1 );
|
||||
|
||||
endAnimDelta = GetMoveDelta( endAnim, 0, 1 );
|
||||
|
||||
endNode = self getnegotiationendnode();
|
||||
assert( isdefined( endnode ) );
|
||||
endPos = endnode.origin - endAnimDelta + ( 0, 0, 1 ); // 1 unit padding
|
||||
|
||||
cycleDelta = GetMoveDelta( climbAnim, 0, 1 );
|
||||
climbRate = cycleDelta[ 2 ] / getanimlength( climbAnim );
|
||||
//("ladder_up: about to start climbing. Height to climb: " + (endAnimDelta[2] + endPos[2] - self.origin[2]) );#/
|
||||
|
||||
climbingTime = ( endPos[ 2 ] - self.origin[ 2 ] ) / climbRate;
|
||||
if ( climbingTime > 0 )
|
||||
{
|
||||
self.allowpain = true;
|
||||
self animscripts\shared::DoNoteTracksForTime( climbingTime, "climbanim" );
|
||||
// println ("elapsed ", (gettime() - timer) * 0.001);
|
||||
self setFlaggedAnimKnoballRestart( "climbanim", endAnim, %body, 1, .1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "climbanim" );
|
||||
}
|
||||
|
||||
self traverseMode( "gravity" );
|
||||
self.a.movement = "run";
|
||||
self.a.pose = "crouch";
|
||||
//("ladder_up: all done");#/
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d112_f244.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d112_f244.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d112_f244;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d128_f50.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d128_f50.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d128_f50;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d160_f160.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d160_f160.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d160_f160;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d160_f244.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d160_f244.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d160_f244;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d200_f600.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d200_f600.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d200_f600;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d220_f640.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d220_f640.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d220_f640;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d240_f328.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d240_f328.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d240_f328;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_d64_f160.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_d64_f160.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_d64_f160;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
14
animscripts/traverse/moon_trav_jump_into_train_f104.gsc
Normal file
14
animscripts/traverse/moon_trav_jump_into_train_f104.gsc
Normal file
@ -0,0 +1,14 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_lava_jump_into_train_f104;
|
||||
traverseData[ "traverseToCoverAnim" ] = %tp_moon_lava_jump_into_train_f104;
|
||||
traverseData[ "coverType" ] = "Exposed";
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
14
animscripts/traverse/moon_trav_jump_into_train_f24.gsc
Normal file
14
animscripts/traverse/moon_trav_jump_into_train_f24.gsc
Normal file
@ -0,0 +1,14 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_lava_jump_into_train_f24;
|
||||
traverseData[ "traverseToCoverAnim" ] = %tp_moon_lava_jump_into_train_f24;
|
||||
traverseData[ "coverType" ] = "Exposed";
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
14
animscripts/traverse/moon_trav_jump_into_train_f352.gsc
Normal file
14
animscripts/traverse/moon_trav_jump_into_train_f352.gsc
Normal file
@ -0,0 +1,14 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_lava_jump_into_train_f352;
|
||||
traverseData[ "traverseToCoverAnim" ] = %tp_moon_lava_jump_into_train_f352;
|
||||
traverseData[ "coverType" ] = "Cover Crouch";
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
15
animscripts/traverse/moon_trav_jump_traintop_f104.gsc
Normal file
15
animscripts/traverse/moon_trav_jump_traintop_f104.gsc
Normal file
@ -0,0 +1,15 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_lava_jump_traintop_f104;
|
||||
traverseData[ "traverseToCoverAnim" ] = %tp_moon_lava_jump_traintop_f104;
|
||||
traverseData[ "coverType" ] = "Cover Right";
|
||||
traverseData[ "forceTeleport" ] = true;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_u36_f_d188.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_u36_f_d188.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u36_f_d188;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_u36_f_d248.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_u36_f_d248.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u36_f_d248;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_u36_f_d284.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_u36_f_d284.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u36_f_d284;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_jump_u48.gsc
Normal file
12
animscripts/traverse/moon_trav_jump_u48.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u48;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
12
animscripts/traverse/moon_trav_storage_jump.gsc
Normal file
12
animscripts/traverse/moon_trav_storage_jump.gsc
Normal file
@ -0,0 +1,12 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_storage_jump;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
40
animscripts/traverse/moon_trav_wall_hop_u_40_d_40.gsc
Normal file
40
animscripts/traverse/moon_trav_wall_hop_u_40_d_40.gsc
Normal file
@ -0,0 +1,40 @@
|
||||
// moon_trav_wall_hop_u_40_d_40.gsc
|
||||
// Makes the character climb a 40 unit fence, lunar
|
||||
|
||||
#include animscripts\traverse\shared;
|
||||
|
||||
main()
|
||||
{
|
||||
wall_hop_human();
|
||||
}
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
wall_hop_human()
|
||||
{
|
||||
if( !IsDefined( level.moon_trav_wall_hop_toggle ) )
|
||||
{
|
||||
level.moon_trav_wall_hop_toggle = 1;
|
||||
}
|
||||
|
||||
if ( level.moon_trav_wall_hop_toggle == 1 )
|
||||
{
|
||||
level.moon_trav_wall_hop_toggle = 0;
|
||||
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u40_f_d40_a;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
level.moon_trav_wall_hop_toggle = 1;
|
||||
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %tp_moon_trav_jump_u40_f_d40_b;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
|
||||
}
|
||||
}
|
19
animscripts/traverse/nx_proto_retro_jump_down_run.gsc
Normal file
19
animscripts/traverse/nx_proto_retro_jump_down_run.gsc
Normal file
@ -0,0 +1,19 @@
|
||||
#include animscripts\utility;
|
||||
#include animscripts\traverse\shared;
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 3, 1.0 );
|
||||
else
|
||||
retro_jump_down_human();
|
||||
}
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
retro_jump_down_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %nx_proto_retro_jump_down_run;
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
378
animscripts/traverse/shared.gsc
Normal file
378
animscripts/traverse/shared.gsc
Normal file
@ -0,0 +1,378 @@
|
||||
#include animscripts\utility;
|
||||
#include maps\_utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
// Deprecated. only used for old traverses that will be deleted.
|
||||
advancedTraverse( traverseAnim, normalHeight )
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );// So he doesn't get stuck if the wall is a little too high
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
realHeight = startnode.traverse_height - startnode.origin[ 2 ];
|
||||
|
||||
self thread teleportThread( realHeight - normalHeight );
|
||||
|
||||
blendTime = 0.15;
|
||||
|
||||
self clearAnim( %body, blendTime );
|
||||
self setFlaggedAnimKnoballRestart( "traverse", traverseAnim, %root, 1, blendTime, 1 );
|
||||
|
||||
gravityToBlendTime = 0.2;
|
||||
endBlendTime = 0.2;
|
||||
|
||||
self thread animscripts\shared::DoNoteTracksForever( "traverse", "no clear" );
|
||||
if ( !animHasNotetrack( traverseAnim, "gravity on" ) )
|
||||
{
|
||||
magicWhateverTime_WhereTheHeckDidWeGetThisNumberAnyway = 1.23;
|
||||
wait( magicWhateverTime_WhereTheHeckDidWeGetThisNumberAnyway - gravityToBlendTime );
|
||||
self traverseMode( "gravity" );
|
||||
wait( gravityToBlendTime );
|
||||
}
|
||||
else
|
||||
{
|
||||
self waittillmatch( "traverse", "gravity on" );
|
||||
self traverseMode( "gravity" );
|
||||
if ( !animHasNotetrack( traverseAnim, "blend" ) )
|
||||
wait( gravityToBlendTime );
|
||||
else
|
||||
self waittillmatch( "traverse", "blend" );
|
||||
}
|
||||
}
|
||||
|
||||
teleportThread( verticalOffset )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self notify( "endTeleportThread" );
|
||||
self endon( "endTeleportThread" );
|
||||
|
||||
reps = 5;
|
||||
offset = ( 0, 0, verticalOffset / reps );
|
||||
|
||||
for ( i = 0; i < reps; i++ )
|
||||
{
|
||||
self forceTeleport( self.origin + offset );
|
||||
wait .05;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
teleportThreadEx( verticalOffset, delay, frames, animRate )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self notify( "endTeleportThread" );
|
||||
self endon( "endTeleportThread" );
|
||||
|
||||
if ( (verticalOffset == 0) || (frames <= 0) )
|
||||
return;
|
||||
|
||||
if ( delay > 0 )
|
||||
wait delay;
|
||||
|
||||
offset = ( 0, 0, verticalOffset / frames );
|
||||
|
||||
if ( isDefined( animRate ) && (animRate < 1.0) )
|
||||
self setFlaggedAnimKnoball( "traverseAnim", self.traverseAnim, self.traverseAnimRoot, 1, .2, animRate );
|
||||
|
||||
for ( i = 0; i < frames; i++ )
|
||||
{
|
||||
self forceTeleport( self.origin + offset );
|
||||
wait .05;
|
||||
}
|
||||
|
||||
if ( isDefined( animRate ) && (animRate < 1.0) )
|
||||
self setFlaggedAnimKnoball( "traverseAnim", self.traverseAnim, self.traverseAnimRoot, 1, .2, 1.0 );
|
||||
}
|
||||
|
||||
|
||||
DoTraverse( traverseData )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
self notify( "traverse_started" );
|
||||
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getNegotiationStartNode();
|
||||
endNode = self getNegotiationEndNode();
|
||||
|
||||
assert( isDefined( startnode ) );
|
||||
assert( isDefined( endNode ) );
|
||||
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self.traverseHeight = traverseData[ "traverseHeight" ];
|
||||
self.traverseStartNode = startnode;
|
||||
|
||||
traverseAnim = traverseData[ "traverseAnim" ];
|
||||
traverseToCoverAnim = traverseData[ "traverseToCoverAnim" ]; // traversals that end up with 180-degree spins into cover at the end
|
||||
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
self.traverseStartZ = self.origin[ 2 ];
|
||||
if ( !animHasNotetrack( traverseAnim, "traverse_align" ) )
|
||||
{
|
||||
/# println( "^1Warning: animation ", traverseAnim, " has no traverse_align notetrack" ); #/
|
||||
self handleTraverseAlignment();
|
||||
}
|
||||
|
||||
toCover = false;
|
||||
if ( isDefined( traverseToCoverAnim ) && isDefined( self.node ) && self.node.type == traverseData[ "coverType" ] && distanceSquared( self.node.origin, endNode.origin ) < 25 * 25 )
|
||||
{
|
||||
if ( AbsAngleClamp180( self.node.angles[ 1 ] - endNode.angles[ 1 ] ) > 160 )
|
||||
{
|
||||
toCover = true;
|
||||
traverseAnim = traverseToCoverAnim;
|
||||
}
|
||||
}
|
||||
|
||||
if ( toCover )
|
||||
{
|
||||
if ( isdefined( traverseData[ "traverseToCoverSound" ] ) )
|
||||
{
|
||||
self thread play_sound_on_entity( traverseData[ "traverseToCoverSound" ] );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isdefined( traverseData[ "traverseSound" ] ) )
|
||||
{
|
||||
self thread play_sound_on_entity( traverseData[ "traverseSound" ] );
|
||||
}
|
||||
}
|
||||
self.traverseAnim = traverseAnim;
|
||||
self.traverseAnimRoot = %body;
|
||||
|
||||
// tagJW<NOTE>: Use the blend_finish tag to determine blend time on the traverse animation
|
||||
blend_time = 0.2;
|
||||
|
||||
if( self IsCQBWalking() )
|
||||
{
|
||||
blend_finish_time = GetNotetrackTimes( traverseAnim, "cqb_blend_finish" );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
blend_finish_time = GetNotetrackTimes( traverseAnim, "blend_finish" );
|
||||
}
|
||||
|
||||
if ( blend_finish_time.size > 0 )
|
||||
{
|
||||
blend_time = blend_finish_time[0] * GetAnimLength( traverseAnim );
|
||||
}
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "traverseAnim", traverseAnim, %body, 1, blend_time, 1 );
|
||||
|
||||
self.traverseDeathIndex = 0;
|
||||
self.traverseDeathAnim = traverseData[ "interruptDeathAnim" ];
|
||||
self animscripts\shared::DoNoteTracks( "traverseAnim", ::handleTraverseNotetracks );
|
||||
self traverseMode( "gravity" );
|
||||
|
||||
if ( self.delayedDeath )
|
||||
return;
|
||||
|
||||
self.a.nodeath = false;
|
||||
if ( toCover && isDefined( self.node ) && distanceSquared( self.origin, self.node.origin ) < 16 * 16 )
|
||||
{
|
||||
self.a.movement = "stop";
|
||||
|
||||
if( IsDefined( traverseData[ "forceTeleport" ] ) && traverseData[ "forceTeleport" ] )
|
||||
{
|
||||
self ForceTeleport( self.node.origin );
|
||||
}
|
||||
else
|
||||
{
|
||||
self Teleport( self.node.origin );
|
||||
}
|
||||
}
|
||||
else if( IsDefined( traverseData[ "traverseStopsAtEnd" ] ) )
|
||||
{
|
||||
self.a.movement = "stop";
|
||||
}
|
||||
else
|
||||
{
|
||||
self.a.movement = "run";
|
||||
//self setAnimKnobAllRestart( animscripts\run::GetRunAnim(), %body, 1, 0.0, 1 );
|
||||
self clearanim( traverseAnim, 0.2 );
|
||||
self animscripts\utility::handle_move_transition_notes( traverseAnim );
|
||||
}
|
||||
|
||||
self notify( "traverse_finished" );
|
||||
|
||||
self.traverseAnimRoot = undefined;
|
||||
self.traverseAnim = undefined;
|
||||
self.deathAnim = undefined;
|
||||
}
|
||||
|
||||
handleTraverseNotetracks( note )
|
||||
{
|
||||
if ( note == "traverse_death" )
|
||||
return handleTraverseDeathNotetrack();
|
||||
else if ( note == "traverse_align" )
|
||||
return handleTraverseAlignment();
|
||||
else if ( note == "traverse_drop" )
|
||||
return handleTraverseDrop();
|
||||
}
|
||||
|
||||
handleTraverseDeathNotetrack()
|
||||
{
|
||||
if ( isdefined( self.traverseDeathAnim ) )
|
||||
{
|
||||
deathAnimArray = self.traverseDeathAnim[ self.traverseDeathIndex ];
|
||||
self.deathAnim = deathAnimArray[ randomint( deathAnimArray.size ) ];
|
||||
self.traverseDeathIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
handleTraverseAlignment()
|
||||
{
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
if ( isDefined( self.traverseHeight ) && isDefined( self.traverseStartNode.traverse_height ) )
|
||||
{
|
||||
currentHeight = self.traverseStartNode.traverse_height - self.traverseStartZ;
|
||||
self thread teleportThread( currentHeight - self.traverseHeight );
|
||||
}
|
||||
}
|
||||
|
||||
handleTraverseDrop()
|
||||
{
|
||||
startpos = self.origin + ( 0, 0, 32 );
|
||||
trace = bullettrace( startpos, self.origin + ( 0, 0, -512 ), false, undefined );
|
||||
endpos = trace[ "position" ];
|
||||
dist = distance( startpos, endpos );
|
||||
realDropHeight = dist - 32 - 0.5;// 0.5 makes sure we end up above the ground a bit
|
||||
|
||||
traverseAnimPos = self getAnimTime( self.traverseAnim );
|
||||
traverseAnimDelta = getMoveDelta( self.traverseAnim, traverseAnimPos, 1.0 );
|
||||
traverseAnimLength = getAnimLength( self.traverseAnim );
|
||||
|
||||
animDropHeight = 0 - traverseAnimDelta[ 2 ];
|
||||
assertEx( animDropHeight >= 0, animDropHeight );
|
||||
dropOffset = animDropHeight - realDropHeight;
|
||||
|
||||
/#
|
||||
if ( getdvarint( "scr_traverse_debug" ) )
|
||||
{
|
||||
thread animscripts\utility::debugLine( startpos, endpos, ( 1, 1, 1 ), 2 * 20 );
|
||||
thread animscripts\utility::drawStringTime( "drop offset: " + dropOffset, endpos, ( 1, 1, 1 ), 2 );
|
||||
}
|
||||
#/
|
||||
|
||||
if ( animDropHeight < realDropHeight )
|
||||
animRate = animDropHeight / realDropHeight;
|
||||
else
|
||||
animRate = 1;
|
||||
|
||||
teleportLength = ( traverseAnimLength - traverseAnimPos ) / 3.0; // let's make the teleport take 1/3 of the animation time roughly
|
||||
numFrames = ceil( teleportLength * 20 ); // 0.05 per frame. Maximum number of frames we can use
|
||||
|
||||
self thread teleportThreadEx( dropOffset, 0, numFrames, animRate );
|
||||
self thread finishTraverseDrop( endpos[ 2 ] );
|
||||
}
|
||||
|
||||
finishTraverseDrop( finalz )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
|
||||
finalz += 4.0;
|
||||
while ( 1 )
|
||||
{
|
||||
if ( self.origin[ 2 ] < finalz )
|
||||
{
|
||||
self traverseMode( "gravity" );
|
||||
break;
|
||||
}
|
||||
wait .05;
|
||||
}
|
||||
}
|
||||
|
||||
doNothingFunc()
|
||||
{
|
||||
self animMode( "zonly_physics" );
|
||||
self waittill( "killanimscript" );
|
||||
}
|
||||
|
||||
#using_animtree( "dog" );
|
||||
|
||||
dog_wall_and_window_hop( traverseName, height )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
realHeight = startnode.traverse_height - startnode.origin[ 2 ];
|
||||
self thread teleportThread( realHeight - height );
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
self setflaggedanimrestart( "dog_traverse", anim.dogTraverseAnims[ traverseName ], 1, 0.2, 1 );
|
||||
|
||||
self animscripts\shared::DoNoteTracks( "dog_traverse" );
|
||||
|
||||
self.traverseComplete = true;
|
||||
}
|
||||
|
||||
|
||||
dog_jump_down( frames, rate )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
height = self getNegotiationStartNode().origin[2] - self getNegotiationEndNode().origin[2];
|
||||
self.traverseAnim = anim.dogTraverseAnims[ "jump_down_40" ];
|
||||
self.traverseAnimRoot = %root;
|
||||
self thread teleportThreadEx( 40.0 - height, 0.1, frames, rate );
|
||||
|
||||
self clearanim( %root, 0.2 );
|
||||
self setflaggedanimrestart( "traverseAnim", self.traverseAnim, 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "traverseAnim" );
|
||||
|
||||
self clearanim( self.traverseAnim, 0 ); // start run immediately
|
||||
self traverseMode( "gravity" );
|
||||
self.traverseComplete = true;
|
||||
self.traverseAnimRoot = undefined;
|
||||
self.traverseAnim = undefined;
|
||||
}
|
||||
|
||||
dog_jump_up( height, frames )
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self thread teleportThreadEx( height - 40.0, 0.2, frames );
|
||||
|
||||
self clearanim( %root, 0.25 );
|
||||
self setflaggedanimrestart( "traverseAnim", anim.dogTraverseAnims[ "jump_up_40" ], 1, 0.2, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "traverseAnim" );
|
||||
|
||||
self clearanim( anim.dogTraverseAnims[ "jump_up_40" ], 0 ); // start run immediately
|
||||
self traverseMode( "gravity" );
|
||||
self.traverseComplete = true;
|
||||
}
|
54
animscripts/traverse/slide_across_car.gsc
Normal file
54
animscripts/traverse/slide_across_car.gsc
Normal file
@ -0,0 +1,54 @@
|
||||
#include animscripts\traverse\shared;
|
||||
#include animscripts\utility;
|
||||
#include common_scripts\utility;
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
slide_across_car_dog();
|
||||
else
|
||||
slide_across_car_human();
|
||||
}
|
||||
|
||||
slide_across_car_human()
|
||||
{
|
||||
traverseData = [];
|
||||
traverseData[ "traverseAnim" ] = %slide_across_car;
|
||||
traverseData[ "traverseToCoverAnim" ] = %slide_across_car_2_cover;
|
||||
traverseData[ "coverType" ] = "Cover Crouch";
|
||||
traverseData[ "traverseHeight" ] = 38.0;
|
||||
traverseData[ "interruptDeathAnim" ][ 0 ] = array( %slide_across_car_death );
|
||||
traverseData[ "traverseSound" ] = "npc_car_slide_hood";
|
||||
traverseData[ "traverseToCoverSound" ] = "npc_car_slide_cover";
|
||||
|
||||
DoTraverse( traverseData );
|
||||
}
|
||||
|
||||
#using_animtree( "dog" );
|
||||
|
||||
slide_across_car_dog()
|
||||
{
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "noclip" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self clearanim( %root, 0.1 );
|
||||
self setflaggedanimrestart( "traverse", anim.dogTraverseAnims[ "jump_up_40" ], 1, 0.1, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "traverse" );
|
||||
|
||||
// TEMP, can't hear jump over sounds
|
||||
self thread play_sound_in_space( "anml_dog_bark", self gettagorigin( "tag_eye" ) );
|
||||
|
||||
self clearanim( %root, 0 );
|
||||
self setflaggedanimrestart( "traverse", anim.dogTraverseAnims[ "jump_down_40" ], 1, 0, 1 );
|
||||
self animscripts\shared::DoNoteTracks( "traverse" );
|
||||
|
||||
self traverseMode( "gravity" );
|
||||
self.traverseComplete = true;
|
||||
}
|
49
animscripts/traverse/stairs_down.gsc
Normal file
49
animscripts/traverse/stairs_down.gsc
Normal file
@ -0,0 +1,49 @@
|
||||
// stairs_down.gsc
|
||||
// Climbs down stairs of any height by using a looping animation.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "stand";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
|
||||
|
||||
endnode = self getnegotiationendnode()
|
||||
assert( isdefined( endnode ) );
|
||||
endPos = endnode.origin;
|
||||
|
||||
horizontalDelta = ( endPos[ 0 ] - self.origin[ 0 ], endPos[ 1 ] - self.origin[ 1 ], 0 );
|
||||
horizontalDistance = length( horizontalDelta );
|
||||
|
||||
// Do the cycle
|
||||
//if ( self animscripts\utility::weaponAnims() == "none" || self animscripts\utility::weaponAnims() == "pistol" )
|
||||
// climbAnim = %climbstairs_down;
|
||||
//else
|
||||
climbAnim = %climbstairs_down_armed;
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startNode ) );
|
||||
self OrientMode( "face angle", node.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoball( "climbanim", climbAnim, %body, 1, .3, 1 );
|
||||
|
||||
cycleDelta = GetMoveDelta( climbAnim, 0, 1 );
|
||||
cycleDelta = ( cycleDelta[ 0 ], cycleDelta[ 1 ], 0 );
|
||||
cycleHorDist = length( cycleDelta );
|
||||
cycleTime = getanimlength( climbAnim );
|
||||
climbingTime = ( horizontalDistance / cycleHorDist ) * cycleTime;
|
||||
|
||||
//("stairs_down: about to start climbing. Horizontal dist: " +horizontalDistance+ ", dist/cycle: "+cycleHorDist+", time/cycle: "+cycleTime+", time to play: "+climbingTime);#/
|
||||
self animscripts\shared::DoNoteTracksForTime( climbingTime, "climbanim" );
|
||||
|
||||
// self traverseMode("gravity");
|
||||
self.a.movement = "walk";
|
||||
self.a.pose = "stand";
|
||||
//("stairs_down: all done");#/
|
||||
}
|
47
animscripts/traverse/stairs_up.gsc
Normal file
47
animscripts/traverse/stairs_up.gsc
Normal file
@ -0,0 +1,47 @@
|
||||
// stairs_up.gsc
|
||||
// Climbs stairs of any height by using a looping animation, and gets off at the top.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self traverseMode( "nogravity" );
|
||||
|
||||
//if ( self animscripts\utility::weaponAnims() == "none" || self animscripts\utility::weaponAnims() == "pistol" )
|
||||
// climbAnim = %climbstairs_up;
|
||||
//else
|
||||
climbAnim = %climbstairs_up_armed;
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startNode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "climbanim", climbAnim, %body, 1, .1, 1 );
|
||||
|
||||
endnode = self getnegotiationendnode();
|
||||
assert( isdefined( endnode ) );
|
||||
endPos = endnode.origin + ( 0, 0, 1 ); // 1 unit padding
|
||||
|
||||
horizontalDelta = ( endPos[ 0 ] - self.origin[ 0 ], endPos[ 1 ] - self.origin[ 1 ], 0 );
|
||||
horizontalDistance = length( horizontalDelta );
|
||||
cycleDelta = GetMoveDelta( climbAnim, 0, 1 );
|
||||
cycleDelta = ( cycleDelta[ 0 ], cycleDelta[ 1 ], 0 );
|
||||
cycleHorDist = length( cycleDelta );
|
||||
cycleTime = getanimlength( climbAnim );
|
||||
climbingTime = ( horizontalDistance / cycleHorDist ) * cycleTime;
|
||||
//("stairs_down: about to start climbing. Horizontal dist: " +horizontalDistance+ ", dist/cycle: "+cycleHorDist+", time/cycle: "+cycleTime+", time to play: "+climbingTime);#/
|
||||
|
||||
self animscripts\shared::DoNoteTracksForTime( climbingTime, "climbanim" );
|
||||
|
||||
// self traverseMode("gravity");
|
||||
self.a.movement = "walk";
|
||||
self.a.pose = "stand";
|
||||
//("stairs_up: all done");#/
|
||||
}
|
||||
|
39
animscripts/traverse/step_down.gsc
Normal file
39
animscripts/traverse/step_down.gsc
Normal file
@ -0,0 +1,39 @@
|
||||
#include animscripts\traverse\shared;
|
||||
|
||||
// step_down.gsc
|
||||
// Makes the character step down off a ledge. Currently the ledge is assumed to be 36 units.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_down( 40, 3 );
|
||||
else
|
||||
step_down_human();
|
||||
}
|
||||
|
||||
|
||||
step_down_human()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self.a.movement = "walk";
|
||||
self traverseMode( "nogravity" );
|
||||
// self traverseMode("noclip"); // Testing to see if a clip brush will stop regular pathfinding and force the traverse script to be used.
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "stepanim", %step_down_low_wall, %body, 1, .1, 1 );
|
||||
self waittillmatch( "stepanim", "gravity on" );
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "stepanim" );
|
||||
}
|
38
animscripts/traverse/step_up.gsc
Normal file
38
animscripts/traverse/step_up.gsc
Normal file
@ -0,0 +1,38 @@
|
||||
#include animscripts\traverse\shared;
|
||||
|
||||
// step_up.gsc
|
||||
// Makes the character step up onto a ledge. Currently the ledge is assumed to be 36 units.
|
||||
|
||||
#using_animtree( "generic_human" );
|
||||
|
||||
main()
|
||||
{
|
||||
if ( self.type == "dog" )
|
||||
dog_jump_up( 40, 3 );
|
||||
else
|
||||
step_up_human();
|
||||
}
|
||||
|
||||
step_up_human()
|
||||
{
|
||||
// do not do code prone in this script
|
||||
self.desired_anim_pose = "crouch";
|
||||
animscripts\utility::UpdateAnimPose();
|
||||
|
||||
self endon( "killanimscript" );
|
||||
self.a.movement = "walk";
|
||||
self traverseMode( "nogravity" );
|
||||
|
||||
// orient to the Negotiation start node
|
||||
startnode = self getnegotiationstartnode();
|
||||
assert( isdefined( startnode ) );
|
||||
self OrientMode( "face angle", startnode.angles[ 1 ] );
|
||||
|
||||
|
||||
self setFlaggedAnimKnoballRestart( "stepanim", %step_up_low_wall, %body, 1, .1, 1 );
|
||||
self waittillmatch( "stepanim", "gravity on" );
|
||||
self traverseMode( "gravity" );
|
||||
self animscripts\shared::DoNoteTracks( "stepanim" );
|
||||
self setAnimKnobAllRestart( animscripts\run::GetCrouchRunAnim(), %body, 1, 0.1, 1 );
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user