IW4-Dump-Files/animscripts/corner.gsc

1415 lines
35 KiB
Plaintext

#include maps\_utility;
#include animscripts\Combat_utility;
#include animscripts\utility;
#include common_scripts\Utility;
#using_animtree( "generic_human" );
corner_think( direction, nodeAngleOffset )
{
self endon( "killanimscript" );
self.animArrayFuncs[ "exposed" ][ "stand" ] = animscripts\corner::set_standing_animarray_aiming;
self.animArrayFuncs[ "exposed" ][ "crouch" ] = animscripts\corner::set_crouching_animarray_aiming;
self.coverNode = self.node;
self.cornerDirection = direction;
self.a.cornerMode = "unknown";
self.a.aimIdleThread = undefined;
animscripts\cover_behavior::turnToMatchNodeDirection( nodeAngleOffset );
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 = ::mainLoopStart;
behaviorCallbacks.reload = ::cornerReload;
behaviorCallbacks.leaveCoverAndShoot = ::stepOutAndShootEnemy;
behaviorCallbacks.look = ::lookForEnemy;
behaviorCallbacks.fastlook = ::fastlook;
behaviorCallbacks.idle = ::idle;
behaviorCallbacks.grenade = ::tryThrowingGrenade;
behaviorCallbacks.grenadehidden = ::tryThrowingGrenadeStayHidden;
behaviorCallbacks.blindfire = ::blindfire;
animscripts\cover_behavior::main( behaviorCallbacks );
}
end_script_corner()
{
self.stepOutYaw = undefined;
self.a.leanAim = undefined;
}
set_corner_anim_array()
{
if ( self.a.pose == "crouch" )
{
set_anim_array( "crouch" );
}
else if ( self.a.pose == "stand" )
{
set_anim_array( "stand" );
}
else
{
assert( self.a.pose == "prone" );
self ExitProneWrapper( 1 );
self.a.pose = "crouch";
self set_anim_array( "crouch" );
}
}
shouldChangeStanceForFun() // and for variety
{
if ( !isDefined( self.enemy ) )
return false;
if ( !isDefined( self.changeStanceForFunTime ) )
self.changeStanceForFunTime = gettime() + randomintrange( 5000, 20000 );
if ( gettime() > self.changeStanceForFunTime )
{
self.changeStanceForFunTime = gettime() + randomintrange( 5000, 20000 );
if ( isDefined( self.ramboChance ) && self.a.pose == "stand" )
return false;
self.a.prevAttack = undefined;
return true;
}
return false;
}
mainLoopStart()
{
desiredStance = "stand";
if ( self.a.pose == "crouch" )
{
desiredStance = "crouch";
if ( self.coverNode doesNodeAllowStance( "stand" ) )
{
if ( !self.coverNode doesNodeAllowStance( "crouch" ) || shouldChangeStanceForFun() )
desiredStance = "stand";
}
}
else
{
if ( self.coverNode doesNodeAllowStance( "crouch" ) )
{
if ( !self.coverNode doesNodeAllowStance( "stand" ) || shouldChangeStanceForFun() )
desiredStance = "crouch";
}
}
/#
if ( getdvarint( "scr_cornerforcecrouch" ) == 1 )
desiredStance = "crouch";
#/
if ( self.haveGoneToCover )
{
self transitionToStance( desiredStance );
}
else
{
if ( self.a.pose == desiredStance )
{
GoToCover( animArray( "alert_idle" ), .3, .4 );
}
else
{
stanceChangeAnim = animarray( "stance_change" );
GoToCover( stanceChangeAnim, .3, getAnimLength( stanceChangeAnim ) );
set_anim_array( desiredStance );// ( sets anim_pose to stance )
}
assert( self.a.pose == desiredStance );
self.haveGoneToCover = true;
}
}
printYaws()
{
wait( 2 );
for ( ;; )
{
println( "coveryaw = ", self.coverNode GetYawToOrigin( getEnemyEyePos() ) );
printYawToEnemy();
wait( 0.05 );
}
}
// used within canSeeEnemyFromExposed() (in utility.gsc)
canSeePointFromExposedAtCorner( point, node )
{
yaw = node GetYawToOrigin( point );
if ( ( yaw > 60 ) || ( yaw < - 60 ) )
return false;
if ( ( node.type == "Cover Left" ) && yaw > 14 )
return false;
if ( ( node.type == "Cover Right" ) && yaw < - 12 )
return false;
return true;
}
shootPosOutsideLegalYawRange()
{
if ( !isdefined( self.shootPos ) )
return false;
yaw = self.coverNode GetYawToOrigin( self.shootPos );
if ( self.a.cornerMode == "over" )
return yaw < self.leftAimLimit || self.rightAimLimit < yaw;
if ( self.cornerDirection == "left" )
{
if ( self.a.cornerMode == "B" )
{
return yaw < 0 - self.ABangleCutoff || yaw > 14;
}
else if ( self.a.cornerMode == "A" )
{
return yaw > 0 - self.ABangleCutoff;
}
else
{
assert( self.a.cornerMode == "lean" );
return yaw < - 50 || yaw > 8;// TODO
}
}
else
{
assert( self.cornerDirection == "right" );
if ( self.a.cornerMode == "B" )
{
return yaw > self.ABangleCutoff || yaw < - 12;
}
else if ( self.a.cornerMode == "A" )
{
return yaw < self.ABangleCutoff;
}
else
{
assert( self.a.cornerMode == "lean" );
return yaw > 50 || yaw < - 8;// TODO
}
}
}
// getCornerMode will return "none" if no corner modes are acceptable.
getCornerMode( node, point )
{
noStepOut = false;
yaw = 0;
if ( isdefined( point ) )
yaw = node GetYawToOrigin( point );
modes = [];
// don't want to get cover peekouts for crouch while standing
if ( isdefined( node ) && self.a.pose == "crouch" && ( yaw > self.leftAimLimit && self.rightAimLimit > yaw ) )
modes = node GetValidCoverPeekOuts();
if ( self.cornerDirection == "left" )
{
if ( canLean( yaw, -40, 0 ) )
{
noStepOut = shouldLean();
modes[ modes.size ] = "lean";
}
if ( !noStepOut && yaw < 14 )
{
if ( yaw < 0 - self.ABangleCutoff )
modes[ modes.size ] = "A";
else
modes[ modes.size ] = "B";
}
}
else
{
assert( self.cornerDirection == "right" );
if ( canLean( yaw, 0, 40 ) )
{
noStepOut = shouldLean();
modes[ modes.size ] = "lean";
}
if ( !noStepOut && yaw > -12 )
{
if ( yaw > self.ABangleCutoff )
modes[ modes.size ] = "A";
else
modes[ modes.size ] = "B";
}
}
return getRandomCoverMode( modes );
}
// getBestStepOutPos never returns "none".
// it returns the best stepoutpos that we can get to from our current one.
getBestStepOutPos()
{
yaw = 0;
if ( canSuppressEnemy() )
yaw = self.coverNode GetYawToOrigin( getEnemySightPos() );
else if ( self.doingAmbush && isdefined( self.shootPos ) )
yaw = self.coverNode GetYawToOrigin( self.shootPos );
/#
dvarval = getdvar( "scr_cornerforcestance" );
if ( dvarval == "lean" || dvarval == "a" || dvarval == "b" )
return dvarval;
#/
if ( self.a.cornerMode == "lean" )
return "lean";
if ( self.a.cornerMode == "over" )
return "over";
else if ( self.a.cornerMode == "B" )
{
if ( self.cornerDirection == "left" )
{
if ( yaw < 0 - self.ABangleCutoff )
return "A";
}
else if ( self.cornerDirection == "right" )
{
if ( yaw > self.ABangleCutoff )
return "A";
}
return "B";
}
else if ( self.a.cornerMode == "A" )
{
positionToSwitchTo = "B";
if ( self.cornerDirection == "left" )
{
if ( yaw > 0 - self.ABangleCutoff )
return "B";
}
else if ( self.cornerDirection == "right" )
{
if ( yaw < self.ABangleCutoff )
return "B";
}
return "A";
}
}
changeStepOutPos()
{
self endon( "killanimscript" );
positionToSwitchTo = getBestStepOutPos();
if ( positionToSwitchTo == self.a.cornerMode )
return false;
// can't switch between lean/over and other stepoutposes
// so if this assert fails then getBestStepOutPos gave us a bad return value
assert( self.a.cornerMode != "lean" && positionToSwitchTo != "lean" );
assert( self.a.cornerMode != "over" && positionToSwitchTo != "over" );
self.changingCoverPos = true; self notify( "done_changing_cover_pos" );
animname = self.a.cornerMode + "_to_" + positionToSwitchTo;
assert( animArrayAnyExist( animname ) );
switchanim = animArrayPickRandom( animname );
midpoint = getPredictedPathMidpoint();
if ( !self mayMoveToPoint( midpoint ) )
return false;
if ( !self mayMoveFromPointToPoint( midpoint, getAnimEndPos( switchanim ) ) )
return false;
self endAimIdleThread();
// turn off aiming while we move.
self StopAiming( .3 );
prev_anim_pose = self.a.pose;
self setanimlimited( animarray( "straight_level" ), 0, .2 );
self setFlaggedAnimKnob( "changeStepOutPos", switchanim, 1, .2, 1.2 );
self thread DoNoteTracksWithEndon( "changeStepOutPos" );
if ( animHasNotetrack( switchanim, "start_aim" ) )
{
self waittillmatch( "changeStepOutPos", "start_aim" );
}
else
{
/#println( "^1Corner position switch animation \"" + animname + "\" in corner_" + self.cornerDirection + " " + self.a.pose + " didn't have \"start_aim\" notetrack" );#/
self waittillmatch( "changeStepOutPos", "end" );
}
self thread StartAiming( undefined, false, .3 );
self waittillmatch( "changeStepOutPos", "end" );
self clearanim( switchanim, .1 );
self.a.cornerMode = positionToSwitchTo;
self.changingCoverPos = false;
self.coverPosEstablishedTime = gettime();
assert( self.a.pose == "stand" || self.a.pose == "crouch" );
if ( self.a.pose != prev_anim_pose )
set_anim_array( self.a.pose );// don't call this if we don't have to, because we don't want to reset %exposed_aiming
self thread ChangeAiming( undefined, true, .3 );
return true;
}
canLean( yaw, yawMin, yawMax )
{
if ( self.a.neverLean )
return false;
return ( yawMin <= yaw && yaw <= yawMax );
}
shouldLean()
{
if ( self.team == "allies" )
return true;
if ( self isPartiallySuppressedWrapper() )
return true;
return false;
}
DoNoteTracksWithEndon( animname )
{
self endon( "killanimscript" );
self animscripts\shared::DoNoteTracks( animname );
}
StartAiming( spot, fullbody, transtime )
{
assert( !self.cornerAiming );
self.cornerAiming = true;
if ( self.a.cornerMode == "lean" )
self.a.leanAim = true;
else
self.a.leanAim = undefined;
self SetAimingParams( spot, fullbody, transTime );
}
ChangeAiming( spot, fullbody, transtime )
{
assert( self.cornerAiming );
if ( self.a.cornerMode == "lean" )
self.a.leanAim = true;
else
self.a.leanAim = undefined;
self SetAimingParams( spot, fullbody, transTime );
}
StopAiming( transtime )
{
assert( self.cornerAiming );
self.cornerAiming = false;
// turn off shooting
self clearAnim( %add_fire, transtime );
// and turn off aiming
animscripts\shared::setAnimAimWeight( 0, transtime );
}
SetAimingParams( spot, fullbody, transTime )
{
assert( isdefined( fullbody ) );
self.spot = spot;// undefined is ok
self setanimlimited( %exposed_modern, 1, transTime );
self setanimlimited( %exposed_aiming, 1, transTime );
self setanimlimited( %add_idle, 1, transTime );
animscripts\shared::setAnimAimWeight( 1, transTime );
leanAnim = undefined;
if ( isdefined( self.a.array[ "lean_aim_straight" ] ) )
leanAnim = self.a.array[ "lean_aim_straight" ];
self thread aimIdleThread();
if ( isdefined( self.a.leanAim ) )
{
self setAnimLimited( leanAnim, 1, transTime );
self setAnimLimited( animArray( "straight_level" ), 0, 0 );
self setAnimKnobLimited( animArray( "lean_aim_left" ), 1, transTime );
self setAnimKnobLimited( animArray( "lean_aim_right" ), 1, transTime );
self setAnimKnobLimited( animArray( "lean_aim_up" ), 1, transTime );
self setAnimKnobLimited( animArray( "lean_aim_down" ), 1, transTime );
}
else if ( fullbody )
{
self setAnimLimited( animarray( "straight_level" ), 1, transTime );
if ( isdefined( leanAnim ) )
self setAnimLimited( leanAnim, 0, 0 );
self setAnimKnobLimited( animArray( "add_aim_up" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_aim_down" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_aim_left" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_aim_right" ), 1, transTime );
}
else
{
self setAnimLimited( animarray( "straight_level" ), 0, transTime );
if ( isdefined( leanAnim ) )
self setAnimLimited( leanAnim, 0, 0 );
self setAnimKnobLimited( animArray( "add_turn_aim_up" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_turn_aim_down" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_turn_aim_left" ), 1, transTime );
self setAnimKnobLimited( animArray( "add_turn_aim_right" ), 1, transTime );
}
}
// These should be adjusted in animation data
stepOutAndHideSpeed()
{
if ( self.a.cornerMode == "over" )
return 1;
//if ( self.a.cornerMode == "B" )
// return 1;
return randomFasterAnimSpeed();
}
stepOut() /* bool */
{
self.a.cornerMode = "alert";
if ( self.goalRadius < 64 )
self.goalRadius = 64;
self animMode( "zonly_physics" );
if ( self.a.pose == "stand" )
{
self.ABangleCutoff = 38;
}
else
{
assert( self.a.pose == "crouch" );
self.ABangleCutoff = 31;
}
thisNodePose = self.a.pose;
set_anim_array( thisNodePose );
self setDefaultAimLimits(); // do exposed animations once stepped out
newCornerMode = "none";
if ( hasEnemySightPos() )
newCornerMode = getCornerMode( self.coverNode, getEnemySightPos() );
else
newCornerMode = getCornerMode( self.coverNode );
if ( !isdefined( newCornerMode ) )
return false;
animname = "alert_to_" + newCornerMode;
assert( animArrayAnyExist( animname ) );
switchanim = animArrayPickRandom( animname );
if ( newCornerMode == "lean" && !self isPeekOutPosClear() )
return false;
if ( newCornerMode != "over" && !isPathClear( switchanim, newCornerMode != "lean" ) )
return false;
self.a.cornerMode = newCornerMode;
self.a.prevAttack = newCornerMode;
if ( self.a.cornerMode == "lean" )
self setDefaultAimLimits( self.coverNode );
if ( newCornerMode == "A" || newCornerMode == "B" )
self.a.special = "cover_" + self.cornerDirection + "_" + self.a.pose + "_" + newCornerMode;
else if ( newCornerMode == "over" )
self.a.special = "cover_crouch_aim";
else
self.a.special = "none";
self.keepClaimedNodeIfValid = true;
hasStartAim = false;
self.changingCoverPos = true;
self notify( "done_changing_cover_pos" );
animRate = stepOutAndHideSpeed();
self.pushable = false;
self setFlaggedAnimKnobAllRestart( "stepout", switchanim, %root, 1, .2, animRate );
self thread DoNoteTracksWithEndon( "stepout" );
hasStartAim = animHasNotetrack( switchanim, "start_aim" );
if ( hasStartAim )
{
// Store our final step out angle so that we may use it when doing track loop aiming
self.stepOutYaw = self.angles[1] + getAngleDelta( switchanim, 0, 1 );
self waittillmatch( "stepout", "start_aim" );
}
else
{
/#println( "^1Corner stepout animation \"" + animname + "\" in corner_" + self.cornerDirection + " " + self.a.pose + " didn't have \"start_aim\" notetrack" );#/
self waittillmatch( "stepout", "end" );
}
if ( newCornerMode == "B" && coinToss() && self.cornerDirection == "right" )
self.a.special = "corner_right_martyrdom";
set_anim_array_aiming( thisNodePose );
fullbody = ( newCornerMode == "over" );
self StartAiming( undefined, fullbody, .3 );
self thread animscripts\shared::trackShootEntOrPos();
if ( hasStartAim )
{
self waittillmatch( "stepout", "end" );
// Clear the forced yaw after the animation is fully played
self.stepOutYaw = undefined;
}
self ChangeAiming( undefined, true, 0.2 );
self clearAnim( %cover, 0.1 );
self clearAnim( %corner, 0.1 );
self.changingCoverPos = false;
self.coverPosEstablishedTime = gettime();
self.pushable = true;
return true;
}
stepOutAndShootEnemy()
{
self.keepClaimedNodeIfValid = true;
// do rambo behavior sometimes on rambo AI guys. Normal AI never do rambo
if ( isdefined( self.ramboChance ) && randomFloat( 1 ) < self.ramboChance )
{
if ( rambo() )
return true;
}
if ( !StepOut() ) // may not be room to step out
return false;
shootAsTold();
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 );
self thread runCombat();
return;
}
}
returnToCover();
self.keepClaimedNodeIfValid = false;
return true;
}
haventRamboedWithinTime( time )
{
if ( !isdefined( self.lastRamboTime ) )
return true;
return gettime() - self.lastRamboTime > time * 1000;
}
rambo()
{
if ( !hasEnemySightPos() )
return false;
ramboAimOffset = 0;
angle = 90;
yaw = self.coverNode GetYawToOrigin( getEnemySightPos() );
if ( self.cornerDirection == "left" )
yaw = 0 - yaw;
if ( yaw > 30 ) // this cutoff works better visually than 22.5
{
angle = 45;
if ( self.cornerDirection == "left" )
ramboAimOffset = 45;
else
ramboAimOffset = -45;
}
animType = "rambo" + angle;
if ( !animArrayAnyExist( animType ) )
return false;
// commented out so we see rambo a lot, might want to adjust this later
//if ( !haventRamboedWithinTime( 2 ) )
// return false;
// move check
ramboAnim = animArrayPickRandom( animType );
midpoint = getPredictedPathMidpoint( 48 );
if ( !self mayMoveToPoint( midpoint ) )
return false;
// no point doing this check, since the animation will end at the cover node.
//if ( !self mayMoveFromPointToPoint( midpoint, getAnimEndPos( ramboAnim ) ) )
// 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( ramboAimOffset );
self setFlaggedAnimKnobAllRestart( "rambo", ramboAnim, %body, 1, 0, 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;
}
shootAsTold()
{
self maps\_gameskill::didSomethingOtherThanShooting();
while ( 1 )
{
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;
if ( shootPosOutsideLegalYawRange() )
{
if ( !changeStepOutPos() )
{
// if we failed because there's no better step out pos, give up
if ( getBestStepOutPos() == self.a.cornerMode )
break;
// couldn't change position, shoot for a short bit and we'll try again
shootUntilShootBehaviorChangeForTime( .2 );
continue;
}
// if they're moving back and forth too fast for us to respond intelligently to them,
// give up on firing at them for the moment
if ( shootPosOutsideLegalYawRange() )
break;
continue;
}
shootUntilShootBehaviorChange_corner( true );
self clearAnim( %add_fire, .2 );
}
if ( self canReturnToCover( self.a.cornerMode != "lean" ) )
break;
// couldn't return to cover. keep shooting and try again
// (change step out pos if necessary and possible)
if ( shootPosOutsideLegalYawRange() && changeStepOutPos() )
continue;
shootUntilShootBehaviorChangeForTime( .2 );
}
}
shootUntilShootBehaviorChangeForTime( time )
{
self thread notifyStopShootingAfterTime( time );
starttime = gettime();
shootUntilShootBehaviorChange_corner( false );
self notify( "stopNotifyStopShootingAfterTime" );
timepassed = ( gettime() - starttime ) / 1000;
if ( timepassed < time )
wait time - timepassed;
}
notifyStopShootingAfterTime( time )
{
self endon( "killanimscript" );
self endon( "stopNotifyStopShootingAfterTime" );
wait time;
self notify( "stopShooting" );
}
shootUntilShootBehaviorChange_corner( runAngleRangeThread )
{
self endon( "return_to_cover" );
if ( runAngleRangeThread )
self thread angleRangeThread();// gives stopShooting notify when shootPosOutsideLegalYawRange returns true
self thread aimIdleThread();
shootUntilShootBehaviorChange();
}
angleRangeThread()
{
self endon( "killanimscript" );
self notify( "newAngleRangeCheck" );
self endon( "newAngleRangeCheck" );
self endon( "take_cover_at_corner" );
while ( 1 )
{
if ( shootPosOutsideLegalYawRange() )
break;
wait( 0.1 );
}
self notify( "stopShooting" );// For changing shooting pose to compensate for player moving
}
showstate()
{
self.enemy endon( "death" );
self endon( "enemy" );
self endon( "stopshowstate" );
while ( 1 )
{
wait .05;
print3d( self.origin + ( 0, 0, 60 ), self.statetext );
}
}
canReturnToCover( doMidpointCheck )
{
if ( doMidpointCheck )
{
midpoint = getPredictedPathMidpoint();
if ( !self mayMoveToPoint( midpoint ) )
return false;
return self mayMoveFromPointToPoint( midpoint, self.coverNode.origin );
}
else
{
return self mayMoveToPoint( self.coverNode.origin );
}
}
returnToCover()
{
assert( self canReturnToCover( self.a.cornerMode != "lean" ) );
endFireAndAnimIdleThread();
// Go back into hiding.
suppressed = issuppressedWrapper();
self notify( "take_cover_at_corner" );// Stop doing the adjust - stance transition thread
self.changingCoverPos = true;
self notify( "done_changing_cover_pos" );
animname = self.a.cornerMode + "_to_alert";
assert( animArrayAnyExist( animname ) );
switchanim = animArrayPickRandom( animname );
self StopAiming( .3 );
reloading = false;
if ( self.a.cornerMode != "lean" && suppressed && animArrayAnyExist( animname + "_reload" ) && randomfloat( 100 ) < 75 )
{
switchanim = animArrayPickRandom( animname + "_reload" );
reloading = true;
}
rate = stepOutAndHideSpeed();
self clearanim( %body, 0.1 );
self setFlaggedAnimRestart( "hide", switchanim, 1, .1, rate );
self animscripts\shared::DoNoteTracks( "hide" );
if ( reloading )
self animscripts\weaponList::RefillClip();
self.changingCoverPos = false;
if ( self.cornerDirection == "left" )
self.a.special = "cover_left";
else
self.a.special = "cover_right";
self.keepClaimedNodeIfValid = false;
self clearAnim( switchanim, 0.2 );
}
blindfire()
{
if ( !animArrayAnyExist( "blind_fire" ) )
return false;
self animMode( "zonly_physics" );
self.keepClaimedNodeIfValid = true;
self setFlaggedAnimKnobAllRestart( "blindfire", animArrayPickRandom( "blind_fire" ), %body, 1, 0, 1 );
self animscripts\shared::DoNoteTracks( "blindfire" );
self.keepClaimedNodeIfValid = false;
return true;
}
linethread( a, b, col )
{
if ( !isdefined( col ) )
col = ( 1, 1, 1 );
for ( i = 0; i < 100; i++ )
{
line( a, b, col );
wait .05;
}
}
tryThrowingGrenadeStayHidden( throwAt )
{
return tryThrowingGrenade( throwAt, true );
}
tryThrowingGrenade( throwAt, safe )
{
if ( !self mayMoveToPoint( self getPredictedPathMidpoint() ) )
return false;
if ( isdefined( self.dontEverShoot ) || isdefined( throwAt.dontAttackMe ) )
return false;
theanim = undefined;
if ( isdefined( self.ramboChance ) && randomFloat( 1 ) < self.ramboChance )
{
if ( isdefined( self.a.array[ "grenade_rambo" ] ) )
theanim = animArray( "grenade_rambo" );
}
if ( !isdefined( theanim ) )
{
if ( isdefined( safe ) && safe )
{
if ( !isdefined( self.a.array[ "grenade_safe" ] ) )
return false;
theanim = animArray( "grenade_safe" );
}
else
{
if ( !isdefined( self.a.array[ "grenade_exposed" ] ) )
return false;
theanim = animArray( "grenade_exposed" );
}
}
assert( isdefined( theanim ) );
self animMode( "zonly_physics" );// Unlatch the feet
self.keepClaimedNodeIfValid = true;
threwGrenade = TryGrenade( throwAt, theanim );
self.keepClaimedNodeIfValid = false;
return threwGrenade;
}
printYawToEnemy()
{
println( "yaw: ", self getYawToEnemy() );
}
lookForEnemy( lookTime )
{
if ( !isdefined( self.a.array[ "alert_to_look" ] ) )
return false;
self animMode( "zonly_physics" );// Unlatch the feet
self.keepClaimedNodeIfValid = true;
// look out from alert
if ( !peekOut() )
return false;
animscripts\shared::playLookAnimation( animarray( "look_idle" ), lookTime, ::canStopPeeking );
lookanim = undefined;
if ( self isSuppressedWrapper() )
lookanim = animArray( "look_to_alert_fast" );
else
lookanim = animArray( "look_to_alert" );
self setflaggedanimknoballrestart( "looking_end", lookanim, %body, 1, .1, 1.0 );
animscripts\shared::DoNoteTracks( "looking_end" );
self animMode( "zonly_physics" );// Unlatch the feet
self.keepClaimedNodeIfValid = false;
return true;
}
PEEKOUT_OFFSET = 30;
isPeekOutPosClear()
{
assert( isdefined( self.coverNode ) );
eyePos = self geteye();
rightDir = anglestoright( self.coverNode.angles );
if ( self.cornerDirection == "right" )
eyePos = eyePos + (rightDir * PEEKOUT_OFFSET);
else
eyePos = eyePos - (rightDir * PEEKOUT_OFFSET);
lookAtPos = eyePos + anglesToForward( self.coverNode.angles ) * PEEKOUT_OFFSET;
// /# thread debugLine( eyePos, lookAtPos, ( 1, 0, 0 ), 1.5 ); #/
return sightTracePassed( eyePos, lookAtPos, true, self );
}
peekOut()
{
if ( isdefined( self.coverNode.script_dontpeek ) )
return false;
if ( isdefined( self.nextPeekOutAttemptTime ) && gettime() < self.nextPeekOutAttemptTime )
return false;
if ( !self isPeekOutPosClear() )
{
self.nextPeekOutAttemptTime = gettime() + 3000;
return false;
}
peekanim = animArray( "alert_to_look" );
// assuming no delta, so no maymovetopoint check
//if ( !self mayMoveToPoint( getAnimEndPos( peekanim ) ) )
// return false;
// not safe to stop peeking in the middle because it will screw up our deltas
//self thread _peekStop();
//self endon ("stopPeeking");
self setflaggedanimknobAll( "looking_start", peekanim, %body, 1, .2, 1 );
animscripts\shared::DoNoteTracks( "looking_start" );
//self notify ("stopPeekCheckThread");
return true;
}
canStopPeeking()
{
return self mayMoveToPoint( self.coverNode.origin );
}
fastlook()
{
// corner fast look animations aren't set up right.
return false;
/*
if ( !isdefined( self.a.array["look"] ) )
return false;
self setFlaggedAnimKnobAllRestart( "look", animArray( "look" ), %body, 1, .1 );
self animscripts\shared::DoNoteTracks( "look" );
return true;
*/
}
cornerReload()
{
assert( animArrayAnyExist( "reload" ) );
reloadanim = animArrayPickRandom( "reload" );
self setFlaggedAnimKnobRestart( "cornerReload", reloadanim, 1, .2 );
self animscripts\shared::DoNoteTracks( "cornerReload" );
self animscripts\weaponList::RefillClip();
self setAnimRestart( animarray( "alert_idle" ), 1, .2 );
self clearAnim( reloadanim, .2 );
return true;
}
isPathClear( stepoutanim, doMidpointCheck )
{
if ( doMidpointCheck )
{
midpoint = getPredictedPathMidpoint();
if ( !self maymovetopoint( midpoint ) )
return false;
return self maymovefrompointtopoint( midpoint, getAnimEndPos( stepoutanim ) );
}
else
{
return self maymovetopoint( getAnimEndPos( stepoutanim ) );
}
}
getPredictedPathMidpoint( dist )
{
angles = self.coverNode.angles;
right = anglestoright( angles );
if ( !isdefined( dist ) )
dist = 36;
switch( self.script )
{
case "cover_left":
right = vector_multiply( right, 0-dist );
break;
case "cover_right":
right = vector_multiply( right, dist );
break;
default:
assertEx( 0, "What kind of node is this????" );
}
return self.coverNode.origin + ( right[ 0 ], right[ 1 ], 0 );
}
idle()
{
self endon( "end_idle" );
while ( 1 )
{
useTwitch = ( randomint( 2 ) == 0 && animArrayAnyExist( "alert_idle_twitch" ) );
if ( useTwitch )
idleanim = animArrayPickRandom( "alert_idle_twitch" );
else
idleanim = animarray( "alert_idle" );
playIdleAnimation( idleAnim, useTwitch );
}
}
flinch()
{
if ( !animArrayAnyExist( "alert_idle_flinch" ) )
return false;
playIdleAnimation( animArrayPickRandom( "alert_idle_flinch" ), true );
return true;
}
playIdleAnimation( idleAnim, needsRestart )
{
if ( needsRestart )
self setFlaggedAnimKnobAllRestart( "idle", idleAnim, %body, 1, .1, 1 );
else
self setFlaggedAnimKnobAll( "idle", idleAnim, %body, 1, .1, 1 );
self animscripts\shared::DoNoteTracks( "idle" );
}
set_anim_array( stance )
{
[[ self.animArrayFuncs[ "hiding" ][ stance ] ]]();
[[ self.animArrayFuncs[ "exposed" ][ stance ] ]]();
}
set_anim_array_aiming( stance )
{
[[ self.animArrayFuncs[ "exposed" ][ stance ] ]]();
}
transitionToStance( stance )
{
if ( self.a.pose == stance )
{
set_anim_array( stance );
return;
}
// self ExitProneWrapper(0.5);
self setFlaggedAnimKnobAllRestart( "changeStance", animarray( "stance_change" ), %body );
set_anim_array( stance );// ( sets anim_pose to stance )
self animscripts\shared::DoNoteTracks( "changeStance" );
assert( self.a.pose == stance );
wait( 0.2 );
}
GoToCover( coveranim, transTime, playTime )
{
cornerAngle = GetNodeDirection();
cornerOrigin = GetNodeOrigin();
desiredYaw = cornerAngle + self.hideyawoffset;
self OrientMode( "face angle", desiredYaw );
self animMode( "normal" );
assert( transTime <= playTime );
self thread animscripts\shared::moveToOriginOverTime( cornerOrigin, transTime );
self setFlaggedAnimKnobAllRestart( "coveranim", coveranim, %body, 1, transTime );
self animscripts\shared::DoNoteTracksForTime( playTime, "coveranim" );
while ( AbsAngleClamp180( self.angles[ 1 ] - desiredYaw ) > 1 )
{
self animscripts\shared::DoNoteTracksForTime( 0.1, "coveranim" );
}
self animMode( "zonly_physics" );
if ( self.cornerDirection == "left" )
self.a.special = "cover_left";
else
self.a.special = "cover_right";
}
drawoffset()
{
self endon( "killanimscript" );
for ( ;; )
{
line( self.node.origin + ( 0, 0, 20 ), ( 0, 0, 20 ) + self.node.origin + vector_multiply( anglestoright( self.node.angles + ( 0, 0, 0 ) ), 16 ) );
wait( 0.05 );
}
}
set_standing_animarray_aiming()
{
if ( !isdefined( self.a.array ) )
assertmsg( "set_standing_animarray_aiming_AandC::this function needs to be called after the initial corner set_ functions" );
self.a.array[ "add_aim_up" ] = %exposed_aim_8;
self.a.array[ "add_aim_down" ] = %exposed_aim_2;
self.a.array[ "add_aim_left" ] = %exposed_aim_4;
self.a.array[ "add_aim_right" ] = %exposed_aim_6;
self.a.array[ "add_turn_aim_up" ] = %exposed_turn_aim_8;
self.a.array[ "add_turn_aim_down" ] = %exposed_turn_aim_2;
self.a.array[ "add_turn_aim_left" ] = %exposed_turn_aim_4;
self.a.array[ "add_turn_aim_right" ] = %exposed_turn_aim_6;
self.a.array[ "straight_level" ] = %exposed_aim_5;
if ( self.a.cornerMode == "lean" )
{
// use the lean animations set up in cover_left and cover_right.gsc
leanfire = self.a.array[ "lean_fire" ];
leanSemiFire = self.a.array[ "lean_single" ];
self.a.array[ "fire" ] = leanfire;
self.a.array[ "single" ] = array( leanSemiFire );
self.a.array[ "semi2" ] = leanSemiFire;
self.a.array[ "semi3" ] = leanSemiFire;
self.a.array[ "semi4" ] = leanSemiFire;
self.a.array[ "semi5" ] = leanSemiFire;
self.a.array[ "burst2" ] = leanfire;
self.a.array[ "burst3" ] = leanfire;
self.a.array[ "burst4" ] = leanfire;
self.a.array[ "burst5" ] = leanfire;
self.a.array[ "burst6" ] = leanfire;
}
else
{
self.a.array[ "fire" ] = %exposed_shoot_auto_v2;
self.a.array[ "semi2" ] = %exposed_shoot_semi2;
self.a.array[ "semi3" ] = %exposed_shoot_semi3;
self.a.array[ "semi4" ] = %exposed_shoot_semi4;
self.a.array[ "semi5" ] = %exposed_shoot_semi5;
if ( weapon_pump_action_shotgun() )
self.a.array[ "single" ] = array( %shotgun_stand_fire_1A );
else
self.a.array[ "single" ] = array( %exposed_shoot_semi1 );
self.a.array[ "burst2" ] = %exposed_shoot_burst3;// ( will be limited to 2 shots )
self.a.array[ "burst3" ] = %exposed_shoot_burst3;
self.a.array[ "burst4" ] = %exposed_shoot_burst4;
self.a.array[ "burst5" ] = %exposed_shoot_burst5;
self.a.array[ "burst6" ] = %exposed_shoot_burst6;
}
self.a.array[ "exposed_idle" ] = array( %exposed_idle_alert_v1, %exposed_idle_alert_v2, %exposed_idle_alert_v3 );
}
set_crouching_animarray_aiming()
{
if ( !isdefined( self.a.array ) )
assertmsg( "set_standing_animarray_aiming_AandC::this function needs to be called after the initial corner set_ functions" );
if ( self.a.cornerMode == "over" )
{
self.a.array[ "add_aim_up" ] = %covercrouch_aim8_add;
self.a.array[ "add_aim_down" ] = %covercrouch_aim2_add;
self.a.array[ "add_aim_left" ] = %covercrouch_aim4_add;
self.a.array[ "add_aim_right" ] = %covercrouch_aim6_add;
self.a.array[ "straight_level" ] = %covercrouch_aim5;
anim_array[ "fire" ] = %exposed_shoot_auto_v2;
anim_array[ "semi2" ] = %exposed_shoot_semi2;
anim_array[ "semi3" ] = %exposed_shoot_semi3;
anim_array[ "semi4" ] = %exposed_shoot_semi4;
anim_array[ "semi5" ] = %exposed_shoot_semi5;
anim_array[ "burst2" ] = %exposed_shoot_burst3;// ( will be limited to 2 shots )
anim_array[ "burst3" ] = %exposed_shoot_burst3;
anim_array[ "burst4" ] = %exposed_shoot_burst4;
anim_array[ "burst5" ] = %exposed_shoot_burst5;
anim_array[ "burst6" ] = %exposed_shoot_burst6;
if ( weapon_pump_action_shotgun() )
anim_array[ "single" ] = array( %shotgun_crouch_fire );
else
anim_array[ "single" ] = array( %exposed_shoot_semi1 );
self.a.array[ "exposed_idle" ] = array( %exposed_idle_alert_v1, %exposed_idle_alert_v2, %exposed_idle_alert_v3 );
return;
}
if ( self.a.cornerMode == "lean" )
{
// use the lean animations set up in cover_left and cover_right.gsc
leanfire = self.a.array[ "lean_fire" ];
leanSemiFire = self.a.array[ "lean_single" ];
self.a.array[ "fire" ] = leanfire;
self.a.array[ "single" ] = array( leanSemiFire );
self.a.array[ "semi2" ] = leanSemiFire;
self.a.array[ "semi3" ] = leanSemiFire;
self.a.array[ "semi4" ] = leanSemiFire;
self.a.array[ "semi5" ] = leanSemiFire;
self.a.array[ "burst2" ] = leanfire;
self.a.array[ "burst3" ] = leanfire;
self.a.array[ "burst4" ] = leanfire;
self.a.array[ "burst5" ] = leanfire;
self.a.array[ "burst6" ] = leanfire;
}
else
{
self.a.array[ "fire" ] = %exposed_crouch_shoot_auto_v2;
self.a.array[ "semi2" ] = %exposed_crouch_shoot_semi2;
self.a.array[ "semi3" ] = %exposed_crouch_shoot_semi3;
self.a.array[ "semi4" ] = %exposed_crouch_shoot_semi4;
self.a.array[ "semi5" ] = %exposed_crouch_shoot_semi5;
if ( weapon_pump_action_shotgun() )
self.a.array[ "single" ] = array( %shotgun_crouch_fire );
else
self.a.array[ "single" ] = array( %exposed_crouch_shoot_semi1 );
self.a.array[ "burst2" ] = %exposed_crouch_shoot_burst3;// ( will be limited to 2 shots )
self.a.array[ "burst3" ] = %exposed_crouch_shoot_burst3;
self.a.array[ "burst4" ] = %exposed_crouch_shoot_burst4;
self.a.array[ "burst5" ] = %exposed_crouch_shoot_burst5;
self.a.array[ "burst6" ] = %exposed_crouch_shoot_burst6;
}
self.a.array[ "add_aim_up" ] = %exposed_crouch_aim_8;
self.a.array[ "add_aim_down" ] = %exposed_crouch_aim_2;
self.a.array[ "add_aim_left" ] = %exposed_crouch_aim_4;
self.a.array[ "add_aim_right" ] = %exposed_crouch_aim_6;
self.a.array[ "add_turn_aim_up" ] = %exposed_crouch_turn_aim_8;
self.a.array[ "add_turn_aim_down" ] = %exposed_crouch_turn_aim_2;
self.a.array[ "add_turn_aim_left" ] = %exposed_crouch_turn_aim_4;
self.a.array[ "add_turn_aim_right" ] = %exposed_crouch_turn_aim_6;
self.a.array[ "straight_level" ] = %exposed_crouch_aim_5;
self.a.array[ "exposed_idle" ] = array( %exposed_crouch_idle_alert_v1, %exposed_crouch_idle_alert_v2, %exposed_crouch_idle_alert_v3 );
}
runCombat()
{
self notify( "killanimscript" );
self thread animscripts\combat::main();
}