mirror of
https://github.com/InfinityLoader/IL-GSC.git
synced 2025-06-07 17:17:50 -05:00
396 lines
11 KiB
Plaintext
396 lines
11 KiB
Plaintext
#include animscripts\zombie_SetPoseMovement;
|
||
#include animscripts\combat_utility;
|
||
#include animscripts\zombie_utility;
|
||
#include animscripts\zombie_shared;
|
||
#include common_scripts\utility;
|
||
#using_animtree ("generic_human");
|
||
main()
|
||
{
|
||
self endon("killanimscript");
|
||
[[ self.exception[ "move" ] ]]();
|
||
previousScript = self.a.script;
|
||
animscripts\zombie_utility::initialize("zombie_move");
|
||
if (self.moveMode == "run")
|
||
{
|
||
switch (previousScript)
|
||
{
|
||
case "combat":
|
||
case "stop":
|
||
self animscripts\battleChatter_ai::evaluateMoveEvent (false);
|
||
break;
|
||
case "cover_crouch":
|
||
case "cover_left":
|
||
case "cover_right":
|
||
case "cover_stand":
|
||
case "concealment_crouch":
|
||
case "concealment_stand":
|
||
case "cover_wide_left":
|
||
case "cover_wide_right":
|
||
case "stalingrad_cover_crouch":
|
||
case "Hide":
|
||
case "turret":
|
||
self animscripts\battleChatter_ai::evaluateMoveEvent (true);
|
||
break;
|
||
default:
|
||
self animscripts\battleChatter_ai::evaluateMoveEvent (false);
|
||
break;
|
||
}
|
||
}
|
||
MoveMainLoop();
|
||
}
|
||
MoveMainLoop()
|
||
{
|
||
prevLoopTime = self getAnimTime( %walk_and_run_loops );
|
||
self.a.runLoopCount = RandomInt( 10000 );
|
||
moveMode = self.moveMode;
|
||
if ( IsDefined( self.pathGoalPos ) && DistanceSquared( self.origin, self.pathGoalPos ) < 4096 )
|
||
{
|
||
moveMode = "walk";
|
||
}
|
||
self.needs_run_update = true;
|
||
self sideStepInit();
|
||
for (;;)
|
||
{
|
||
loopTime = self getAnimTime( %walk_and_run_loops );
|
||
if ( loopTime < prevLoopTime )
|
||
{
|
||
self.a.runLoopCount++;
|
||
}
|
||
prevLoopTime = loopTime;
|
||
self animscripts\face::SetIdleFaceDelayed( anim.alertface );
|
||
self animscripts\zombie_run::MoveRun();
|
||
self.exitingCover = false;
|
||
self trySideStep();
|
||
}
|
||
}
|
||
moveAgain()
|
||
{
|
||
self notify("killanimscript");
|
||
animscripts\zombie_move::main();
|
||
}
|
||
sideStepInit()
|
||
{
|
||
self.a.steppedDir = 0;
|
||
self.a.lastSideStepTime = GetTime();
|
||
if( !IsDefined( level.sideStepAnims ) )
|
||
{
|
||
level.MIN_REACTION_DIST_SQ = 64*64;
|
||
level.MAX_REACTION_DIST_SQ = 1000*1000;
|
||
level.REACTION_INTERVAL = 2000;
|
||
level.SIDE_STEP_CHANCE = 0.7;
|
||
level.RIGHT_STEP_CHANCE = 0.5;
|
||
level.FORWARD_REACTION_INTERVAL = 2000;
|
||
level.FORWARD_MIN_REACTION_DIST_SQ = 120*120;
|
||
level.FORWARD_MAX_REACTION_DIST_SQ = 2400*2400;
|
||
level.sideStepAnims = [];
|
||
level.sideStepAnims["step_left"] = array( %ai_zombie_spets_sidestep_left_a, %ai_zombie_spets_sidestep_left_b );
|
||
level.sideStepAnims["step_right"] = array( %ai_zombie_spets_sidestep_right_a, %ai_zombie_spets_sidestep_right_b );
|
||
level.sideStepAnims["roll_forward"] = array( %ai_zombie_spets_roll_a, %ai_zombie_spets_roll_b, %ai_zombie_spets_roll_c );
|
||
}
|
||
}
|
||
trySideStep()
|
||
{
|
||
if ( isdefined( self.shouldSideStepFunc ) )
|
||
{
|
||
self.sideStepType = self [[ self.shouldSideStepFunc ]]();
|
||
}
|
||
else
|
||
{
|
||
self.sideStepType = shouldSideStep();
|
||
}
|
||
if( self.sideStepType == "none" )
|
||
{
|
||
if ( is_true( self.zombie_can_forwardstep ) )
|
||
{
|
||
self.sideStepType = shouldForwardStep();
|
||
}
|
||
}
|
||
if( self.sideStepType == "none" )
|
||
{
|
||
return false;
|
||
}
|
||
self.desiredStepDir = getDesiredSideStepDir( self.sideStepType );
|
||
animName = self.sideStepType + "_" + self.desiredStepDir;
|
||
sideStepAnims = level.sideStepAnims;
|
||
if ( IsDefined( self.sideStepAnims ) )
|
||
{
|
||
sideStepAnims = self.sideStepAnims;
|
||
}
|
||
self.stepAnim = sideStepAnims[ animName ][RandomInt( sideStepAnims[ animName ].size )];
|
||
assertex( IsDefined(self.stepAnim), "Sidestep anim " + animName + " not found" );
|
||
if ( !self checkRoomForAnim( self.stepAnim ) )
|
||
{
|
||
hasRoom = false;
|
||
if( self.sideStepType == "roll" && self.desiredStepDir != "forward" )
|
||
{
|
||
self.desiredStepDir = "forward";
|
||
animName = self.sideStepType + "_" + self.desiredStepDir;
|
||
self.stepAnim = sideStepAnims[ animName ][RandomInt( sideStepAnims[ animName ].size )];
|
||
assertex( IsDefined(self.stepAnim), "Sidestep anim " + animName + " not found" );
|
||
hasRoom = self checkRoomForAnim( self.stepAnim );
|
||
}
|
||
if( !hasRoom )
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
self AnimCustom( ::doSideStep );
|
||
}
|
||
getDesiredSideStepDir( sideStepType )
|
||
{
|
||
if( sideStepType == "roll" || sideStepType == "phase" )
|
||
{
|
||
self.desiredStepDir = "forward";
|
||
return self.desiredStepDir;
|
||
}
|
||
AssertEx( sideStepType == "step", "Unsupported SideStepType" );
|
||
randomRoll = RandomFloat(1);
|
||
if( self.a.steppedDir < 0 )
|
||
{
|
||
self.desiredStepDir = "right";
|
||
}
|
||
else if( self.a.steppedDir > 0 )
|
||
{
|
||
self.desiredStepDir = "left";
|
||
}
|
||
else if( randomRoll < level.RIGHT_STEP_CHANCE )
|
||
{
|
||
self.desiredStepDir = "right";
|
||
}
|
||
else if( randomRoll < level.RIGHT_STEP_CHANCE*2 )
|
||
{
|
||
self.desiredStepDir = "left";
|
||
}
|
||
return self.desiredStepDir;
|
||
}
|
||
checkRoomForAnim( stepAnim )
|
||
{
|
||
if ( !self MayMoveFromPointToPoint( self.origin, getAnimEndPos( stepAnim ) ) )
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
shouldSideStep()
|
||
{
|
||
if( canSideStep() && IsPlayer(self.enemy) && self.enemy IsLookingAt(self) )
|
||
{
|
||
if( self.zombie_move_speed != "sprint" || RandomFloat(1) < level.SIDE_STEP_CHANCE )
|
||
return "step";
|
||
else
|
||
return "roll";
|
||
}
|
||
return "none";
|
||
}
|
||
canSideStep()
|
||
{
|
||
if ( !IsDefined( self.zombie_can_sidestep ) || !self.zombie_can_sidestep )
|
||
{
|
||
if( !issubstr( self.classname, "zombie_spetznaz" ) )
|
||
return false;
|
||
}
|
||
if( GetTime() - self.a.lastSideStepTime < level.REACTION_INTERVAL )
|
||
return false;
|
||
if( !IsDefined(self.enemy) )
|
||
return false;
|
||
if( self.a.pose != "stand" )
|
||
return false;
|
||
distSqFromEnemy = DistanceSquared(self.origin, self.enemy.origin);
|
||
if( distSqFromEnemy < level.MIN_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( distSqFromEnemy > level.MAX_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( !IsDefined(self.pathgoalpos) || DistanceSquared(self.origin, self.pathgoalpos) < level.MIN_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( abs(self GetMotionAngle()) > 15 )
|
||
{
|
||
return false;
|
||
}
|
||
yaw = GetYawToOrigin(self.enemy.origin);
|
||
if( abs(yaw) > 45 )
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
shouldForwardStep()
|
||
{
|
||
if ( canForwardStep() && IsPlayer( self.enemy ) )
|
||
{
|
||
return "phase";
|
||
}
|
||
return "none";
|
||
}
|
||
canForwardStep()
|
||
{
|
||
if ( !isdefined( self.zombie_can_forwardstep ) || !self.zombie_can_forwardstep )
|
||
{
|
||
return false;
|
||
}
|
||
if( GetTime() - self.a.lastSideStepTime < level.FORWARD_REACTION_INTERVAL )
|
||
return false;
|
||
if( !IsDefined(self.enemy) )
|
||
return false;
|
||
if( self.a.pose != "stand" )
|
||
return false;
|
||
distSqFromEnemy = DistanceSquared(self.origin, self.enemy.origin);
|
||
if( distSqFromEnemy < level.FORWARD_MIN_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( distSqFromEnemy > level.FORWARD_MAX_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( !IsDefined(self.pathgoalpos) || DistanceSquared(self.origin, self.pathgoalpos) < level.MIN_REACTION_DIST_SQ )
|
||
{
|
||
return false;
|
||
}
|
||
if( abs(self GetMotionAngle()) > 15 )
|
||
{
|
||
return false;
|
||
}
|
||
yaw = GetYawToOrigin(self.enemy.origin);
|
||
if( abs(yaw) > 45 )
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
doSideStep()
|
||
{
|
||
self endon("death");
|
||
self endon("killanimscript");
|
||
playSideStepAnim( self.stepAnim, self.sideStepType );
|
||
if( self.desiredStepDir == "left" )
|
||
{
|
||
self.a.steppedDir--;
|
||
}
|
||
else
|
||
{
|
||
self.a.steppedDir++;
|
||
}
|
||
self.a.lastSideStepTime = GetTime();
|
||
return true;
|
||
}
|
||
playSideStepAnim( stepAnim, sideStepType )
|
||
{
|
||
self AnimMode( "gravity", false );
|
||
self OrientMode( "face angle", self.angles[1] );
|
||
runBlendOutTime = 0.20;
|
||
if ( isdefined( self.sideStepFunc ) )
|
||
{
|
||
self thread [[ self.sideStepFunc ]]( "stepAnim", stepAnim );
|
||
}
|
||
self ClearAnim( %body, runBlendOutTime );
|
||
self SetFlaggedAnimRestart( "stepAnim", stepAnim, 1, runBlendOutTime, self.moveplaybackrate );
|
||
animStartTime = GetTime();
|
||
animLength = GetAnimLength(stepAnim);
|
||
hasExitAlign = animHasNotetrack( stepAnim, "exit_align" );
|
||
if ( !hasExitAlign )
|
||
{
|
||
println("^1Side step animation has no \"exit_align\" notetrack");
|
||
}
|
||
self thread animscripts\shared::DoNoteTracks( "stepAnim" );
|
||
self thread sideStepBlendOut( animLength, "stepAnim", hasExitAlign );
|
||
self.exit_align = false;
|
||
self waittillmatch( "stepAnim", "exit_align" );
|
||
self.exit_align = true;
|
||
elapsed = (getTime() - animStartTime) / 1000.0;
|
||
timeLeft = animLength - elapsed;
|
||
hasCodeMoveNoteTrack = animHasNotetrack( stepAnim, "code_move" );
|
||
if( hasCodeMoveNoteTrack )
|
||
{
|
||
times = getNotetrackTimes( stepAnim, "code_move" );
|
||
assertEx( times.size == 1, "More than one code_move notetrack found" );
|
||
timeLeft = times[0] * animLength - elapsed;
|
||
}
|
||
self AnimMode( "pos deltas", false );
|
||
maxYawDelta = 2;
|
||
timer = 0;
|
||
while( timer < timeLeft )
|
||
{
|
||
lookaheadAngles = VectorToAngles( self.lookaheaddir );
|
||
yawDelta = AngleClamp180(lookaheadAngles[1] - self.angles[1]);
|
||
if( yawDelta > maxYawDelta )
|
||
{
|
||
yawDelta = maxYawDelta;
|
||
}
|
||
else if( yawDelta < maxYawDelta*-1 )
|
||
{
|
||
yawDelta = maxYawDelta*-1;
|
||
}
|
||
newAngles = (self.angles[0], self.angles[1] + yawDelta, self.angles[2]);
|
||
self Teleport( self.origin, newAngles );
|
||
timer += 0.05 * self.moveplaybackrate;
|
||
wait( 0.05 );
|
||
}
|
||
self OrientMode( "face angle", self.angles[1] );
|
||
elapsed = (getTime() - animStartTime) / 1000.0;
|
||
timeLeft = animLength - elapsed;
|
||
if( timeLeft > 0 )
|
||
{
|
||
wait(timeLeft / self.moveplaybackrate);
|
||
}
|
||
if( IsAlive(self) )
|
||
{
|
||
self thread faceLookaheadForABit();
|
||
restorePain();
|
||
self.deathFunction = maps\_zombiemode_spawner::zombie_death_animscript;
|
||
}
|
||
}
|
||
faceLookaheadForABit()
|
||
{
|
||
self endon("death");
|
||
self endon("killanimscript");
|
||
lookaheadAngles = VectorToAngles(self.lookaheaddir);
|
||
self OrientMode( "face angle", lookaheadAngles[1] );
|
||
wait(0.2);
|
||
self AnimMode( "normal", false );
|
||
self OrientMode( "face default" );
|
||
}
|
||
sideStepBlendOut( animLength, animName, hasExitAlign )
|
||
{
|
||
self endon("killanimscript");
|
||
self endon("death");
|
||
self endon("stopTurnBlendOut");
|
||
runBlendInTime = 0.2;
|
||
assert( animLength > runBlendInTime );
|
||
wait( (animLength - runBlendInTime) / self.moveplaybackrate );
|
||
if( !hasExitAlign )
|
||
{
|
||
self notify( animName, "exit_align" );
|
||
}
|
||
self ClearAnim( %exposed_modern, 0 );
|
||
self SetFlaggedAnimKnobAllRestart( "run_anim", animscripts\zombie_run::GetRunAnim(), %body, 1, runBlendInTime, self.moveplaybackrate );
|
||
}
|
||
restorePainOnKillanimscript()
|
||
{
|
||
self waittill("killanimscript");
|
||
if( IsDefined(self) && IsAlive(self) )
|
||
{
|
||
restorePain();
|
||
self.deathFunction = undefined;
|
||
}
|
||
}
|
||
disablePain()
|
||
{
|
||
self.a.storedDisablePain = self.a.disablePain;
|
||
self.a.storedAllowPain = self.a.allowPain;
|
||
self.a.disablePain = true;
|
||
self.allowPain = false;
|
||
}
|
||
restorePain()
|
||
{
|
||
if( IsDefined(self.a.storedDisablePain) && IsDefined(self.a.storedAllowPain) )
|
||
{
|
||
self.a.disablePain = self.a.storedDisablePain;
|
||
self.allowPain = self.a.storedAllowPain;
|
||
}
|
||
} |