#include animscripts\Combat_utility; #include animscripts\Utility; #include common_scripts\Utility; #using_animtree( "generic_human" ); cover_wall_think( coverType ) { self endon( "killanimscript" ); 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 ) { self setDefaultAimLimits( self.coverNode ); self setup_crouching_anim_array( exposedAnimSet ); } setup_cover_stand( exposedAnimSet ) { self setDefaultAimLimits( self.coverNode ); self setup_standing_anim_array( exposedAnimSet ); } coverReload() { Reload( 2.0, animArray( "reload" ) );// ( reload no matter what ) return true; } 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 } setup_crouching_anim_array( exposedAnimSet ) { anim_array = []; anim_array[ "hide_idle" ] = %covercrouch_hide_idle; anim_array[ "hide_idle_twitch" ] = array( %covercrouch_twitch_1, %covercrouch_twitch_2, %covercrouch_twitch_3, %covercrouch_twitch_4 //%covercrouch_twitch_5 // excluding #5 because it's a wave to someone behind him, and in idle twitches we don't know if that makes sense at the time ); anim_array[ "hide_idle_flinch" ] = array( /*%covercrouch_explosion_1, %covercrouch_explosion_2, %covercrouch_explosion_3*/ // these just don't look good for flinching ); anim_array[ "hide_2_crouch" ] = %covercrouch_hide_2_aim; anim_array[ "hide_2_stand" ] = %covercrouch_hide_2_stand; anim_array[ "hide_2_lean" ] = %covercrouch_hide_2_lean; anim_array[ "hide_2_right" ] = %covercrouch_hide_2_right; anim_array[ "hide_2_left" ] = %covercrouch_hide_2_left; anim_array[ "crouch_2_hide" ] = %covercrouch_aim_2_hide; anim_array[ "stand_2_hide" ] = %covercrouch_stand_2_hide; anim_array[ "lean_2_hide" ] = %covercrouch_lean_2_hide; anim_array[ "right_2_hide" ] = %covercrouch_right_2_hide; anim_array[ "left_2_hide" ] = %covercrouch_left_2_hide; anim_array[ "crouch_aim" ] = %covercrouch_aim5; anim_array[ "stand_aim" ] = %exposed_aim_5; anim_array[ "lean_aim" ] = %covercrouch_lean_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; if ( weapon_pump_action_shotgun() ) { if ( exposedAnimSet == "lean" || exposedAnimSet == "stand" ) anim_array[ "single" ] = array( %shotgun_stand_fire_1A ); else anim_array[ "single" ] = array( %shotgun_crouch_fire ); } else { anim_array[ "single" ] = array( %exposed_shoot_semi1 ); } 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; anim_array[ "blind_fire" ] = array( %covercrouch_blindfire_1, %covercrouch_blindfire_2, %covercrouch_blindfire_3, %covercrouch_blindfire_4 ); anim_array[ "reload" ] = %covercrouch_reload_hide; anim_array[ "grenade_safe" ] = array( %covercrouch_grenadeA, %covercrouch_grenadeB ); anim_array[ "grenade_exposed" ] = array( %covercrouch_grenadeA, %covercrouch_grenadeB ); anim_array[ "exposed_idle" ] = array( %exposed_idle_alert_v1, %exposed_idle_alert_v2, %exposed_idle_alert_v3 ); anim_array[ "look" ] = array( %covercrouch_hide_look ); 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 = []; anim_array[ "hide_idle" ] = %coverstand_hide_idle; anim_array[ "hide_idle_twitch" ] = array( %coverstand_hide_idle_twitch01, %coverstand_hide_idle_twitch02, %coverstand_hide_idle_twitch03, %coverstand_hide_idle_twitch04, %coverstand_hide_idle_twitch05 ); anim_array[ "hide_idle_flinch" ] = array( %coverstand_react01, %coverstand_react02, %coverstand_react03, %coverstand_react04 ); anim_array[ "hide_2_stand" ] = %coverstand_hide_2_aim; anim_array[ "stand_2_hide" ] = %coverstand_aim_2_hide; anim_array[ "hide_2_over" ] = %coverstand_2_coverstandaim; anim_array[ "over_2_hide" ] = %coverstandaim_2_coverstand; if ( exposedAnimSet == "over" ) { anim_array[ "over_aim" ] = %coverstandaim_aim5; anim_array[ "fire" ] = %coverstandaim_autofire; anim_array[ "semi2" ] = %coverstandaim_fire; anim_array[ "semi3" ] = %coverstandaim_fire; anim_array[ "semi4" ] = %coverstandaim_fire; anim_array[ "semi5" ] = %coverstandaim_fire; anim_array[ "single" ] = array( %coverstandaim_fire ); anim_array[ "burst2" ] = %coverstandaim_autofire;// ( will be limited to 2 shots ) anim_array[ "burst3" ] = %coverstandaim_autofire; anim_array[ "burst4" ] = %coverstandaim_autofire; anim_array[ "burst5" ] = %coverstandaim_autofire; anim_array[ "burst6" ] = %coverstandaim_autofire; } else { anim_array[ "stand_aim" ] = %exposed_aim_5; 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; if ( weapon_pump_action_shotgun() ) anim_array[ "single" ] = array( %shotgun_stand_fire_1A ); else anim_array[ "single" ] = array( %exposed_shoot_semi1 ); 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; } anim_array["blind_fire"] = array( %coverstand_blindfire_1, %coverstand_blindfire_2 /*, %coverstand_blindfire_3*/ ); // #3 looks silly anim_array[ "reload" ] = %coverstand_reloadA; anim_array[ "look" ] = array( %coverstand_look_quick, %coverstand_look_quick_v2 ); anim_array[ "grenade_safe" ] = array( %coverstand_grenadeA, %coverstand_grenadeB ); anim_array[ "grenade_exposed" ] = array( %coverstand_grenadeA, %coverstand_grenadeB ); anim_array[ "exposed_idle" ] = array( %exposed_idle_alert_v1, %exposed_idle_alert_v2, %exposed_idle_alert_v3 ); 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; 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 ( 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 ] ); }