mirror of
https://github.com/InfinityLoader/IL-GSC.git
synced 2025-06-07 17:17:50 -05:00
1519 lines
36 KiB
Plaintext
1519 lines
36 KiB
Plaintext
#include animscripts\Utility;
|
||
#include animscripts\Debug;
|
||
#include animscripts\SetPoseMovement;
|
||
#include animscripts\anims;
|
||
#include common_scripts\utility;
|
||
#include maps\_gameskill;
|
||
#include maps\_utility;
|
||
#using_animtree ("generic_human");
|
||
player_init()
|
||
{
|
||
}
|
||
EnemiesWithinStandingRange()
|
||
{
|
||
enemyDistanceSq = self MyGetEnemySqDist();
|
||
return ( enemyDistanceSq < anim.standRangeSq );
|
||
}
|
||
MyGetEnemySqDist()
|
||
{
|
||
dist = self GetClosestEnemySqDist();
|
||
if (!IsDefined(dist))
|
||
{
|
||
dist = 100000000000;
|
||
}
|
||
return dist;
|
||
}
|
||
getTargetAngleOffset(target)
|
||
{
|
||
pos = self GetShootAtPos() + (0,0,-3);
|
||
dir = (pos[0] - target[0], pos[1] - target[1], pos[2] - target[2]);
|
||
dir = VectorNormalize( dir );
|
||
fact = dir[2] * -1;
|
||
return fact;
|
||
}
|
||
getSniperBurstDelayTime()
|
||
{
|
||
return RandomFloatRange( anim.min_sniper_burst_delay_time, anim.max_sniper_burst_delay_time );
|
||
}
|
||
getRemainingBurstDelayTime()
|
||
{
|
||
timeSoFar = (GetTime() - self.a.lastShootTime) / 1000;
|
||
delayTime = getBurstDelayTime();
|
||
if ( delayTime > timeSoFar )
|
||
{
|
||
return delayTime - timeSoFar;
|
||
}
|
||
return 0;
|
||
}
|
||
getBurstDelayTime()
|
||
{
|
||
if ( self usingSidearm() )
|
||
{
|
||
return RandomFloatRange( .15, .55 );
|
||
}
|
||
else if ( self usingShotgun() )
|
||
{
|
||
return RandomFloatRange( 1.0, 1.7 );
|
||
}
|
||
else if ( self isSniper() )
|
||
{
|
||
return getSniperBurstDelayTime();
|
||
}
|
||
else if ( self.fastBurst )
|
||
{
|
||
return RandomFloatRange( .1, .35 );
|
||
}
|
||
else if ( self usingBoltActionWeapon() )
|
||
{
|
||
return RandomFloatRange( 1.0, 1.5 );
|
||
}
|
||
else if ( self usingGrenadeLauncher() )
|
||
{
|
||
return RandomFloatRange( 1.5, 2.0 );
|
||
}
|
||
else if ( is_rusher() && self.rusherType == "pistol" )
|
||
{
|
||
return RandomFloatRange( .1, .3 );
|
||
}
|
||
else
|
||
{
|
||
return RandomFloatRange( .4, .9 );
|
||
}
|
||
}
|
||
burstDelay()
|
||
{
|
||
if ( self.bulletsInClip )
|
||
{
|
||
if ( self.shootStyle == "full" && !self.fastBurst )
|
||
{
|
||
if ( self.a.lastShootTime == GetTime() )
|
||
{
|
||
wait .05;
|
||
}
|
||
return;
|
||
}
|
||
delayTime = getRemainingBurstDelayTime();
|
||
if ( delayTime )
|
||
{
|
||
wait delayTime;
|
||
}
|
||
}
|
||
}
|
||
cheatAmmoIfNecessary()
|
||
{
|
||
assert( !self.bulletsInClip );
|
||
if ( !IsDefined( self.enemy ) )
|
||
{
|
||
return false;
|
||
}
|
||
if( self is_rusher() )
|
||
{
|
||
self.bulletsInClip = weaponClipSize( self.weapon );
|
||
return true;
|
||
}
|
||
if( self.a.idleStrafing )
|
||
{
|
||
self.bulletsInClip = int( min(10, weaponClipSize( self.weapon )) );
|
||
self.nextCheatTime = GetTime() + 8000;
|
||
return true;
|
||
}
|
||
if ( self is_banzai() )
|
||
{
|
||
self.bulletsInClip = weaponClipSize( self.weapon );
|
||
return true;
|
||
}
|
||
if ( self.team == "allies" )
|
||
{
|
||
return false;
|
||
}
|
||
if ( !IsPlayer( self.enemy ) )
|
||
{
|
||
return false;
|
||
}
|
||
if ( weaponClipSize( self.weapon ) < 15 )
|
||
{
|
||
return false;
|
||
}
|
||
if ( flag("player_is_invulnerable") )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self weaponAnims() == "pistol" )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self weaponAnims() == "rocketlauncher" )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self weaponAnims() == "grenade" )
|
||
{
|
||
return false;
|
||
}
|
||
if ( IsDefined( self.nextCheatTime ) && GetTime() < self.nextCheatTime )
|
||
{
|
||
return false;
|
||
}
|
||
if ( !self canSee( self.enemy ) )
|
||
{
|
||
return false;
|
||
}
|
||
if (IsDefined (self.cheatammo_override) && (self.cheatammo_override == true))
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
self.bulletsInClip = 10;
|
||
}
|
||
if ( self.bulletsInClip > weaponClipSize( self.weapon ) )
|
||
{
|
||
self.bulletsInClip = weaponClipSize( self.weapon );
|
||
}
|
||
self.nextCheatTime = GetTime() + 8000;
|
||
return true;
|
||
}
|
||
shootUntilShootBehaviorChange()
|
||
{
|
||
self endon("shoot_behavior_change");
|
||
self endon("stopShooting");
|
||
if ( self weaponAnims() == "rocketlauncher" || self isSniper() )
|
||
{
|
||
players = GetPlayers();
|
||
if( IsDefined( players ) && players.size > 0 )
|
||
{
|
||
if ( IsDefined( self.enemy ) && !IsPlayer(self.enemy) && IsSentient( self.enemy ) )
|
||
{
|
||
if( DistanceSquared( players[0].origin, self.enemy.origin ) < 384*384 )
|
||
{
|
||
self.enemy animscripts\battlechatter_ai::addThreatEvent( "infantry", self, 1.0 );
|
||
}
|
||
}
|
||
}
|
||
if ( self weaponAnims() == "rocketlauncher" && IsSentient( self.enemy ) )
|
||
{
|
||
wait ( RandomFloat( 2.0 ) );
|
||
}
|
||
}
|
||
if ( IsDefined(self.enemy) && DistanceSquared(self.origin, self.enemy.origin) > 400*400 )
|
||
burstCount = RandomIntRange( 1, 5 );
|
||
else
|
||
burstCount = 10;
|
||
while(1)
|
||
{
|
||
burstDelay();
|
||
animPrefix = getShootAnimPrefix();
|
||
if ( self.shootStyle == "full" )
|
||
{
|
||
self FireUntilOutOfAmmo( animArray( animPrefix + "fire" ), false, animscripts\shared::decideNumShotsForFull() );
|
||
}
|
||
else if ( self.shootStyle == "burst" || self.shootStyle == "single" || self.shootStyle == "semi" )
|
||
{
|
||
numShots = 1;
|
||
if ( self.shootStyle == "burst" || self.shootStyle == "semi" )
|
||
{
|
||
numShots = animscripts\shared::decideNumShotsForBurst();
|
||
}
|
||
if ( numShots == 1 )
|
||
{
|
||
self FireUntilOutOfAmmo( animArrayPickRandom( animPrefix + "single" ), true, numShots );
|
||
}
|
||
else
|
||
{
|
||
self FireUntilOutOfAmmo( animArray( animPrefix + self.shootStyle + numShots ), true, numShots );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
assert( self.shootStyle == "none" );
|
||
self waittill( "hell freezes over" );
|
||
}
|
||
if ( !self.bulletsInClip )
|
||
{
|
||
break;
|
||
}
|
||
if ( self usingBoltActionWeapon() )
|
||
{
|
||
break;
|
||
}
|
||
if( animscripts\shared::shouldSwitchWeapons() )
|
||
{
|
||
self notify("need_to_switch_weapons");
|
||
break;
|
||
}
|
||
burstCount--;
|
||
if ( burstCount < 0 )
|
||
{
|
||
self.shouldReturnToCover = true;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
getUniqueFlagNameIndex()
|
||
{
|
||
anim.animFlagNameIndex++;
|
||
return anim.animFlagNameIndex;
|
||
}
|
||
FireUntilOutOfAmmo( fireAnim, stopOnAnimationEnd, maxshots )
|
||
{
|
||
animName = "fireAnim_" + getUniqueFlagNameIndex();
|
||
maps\_gameskill::resetMissTime();
|
||
while( !aimedAtShootEntOrPos() )
|
||
{
|
||
wait .05;
|
||
}
|
||
self SetAnim( %add_fire, 1, .1, 1 );
|
||
rate = RandomFloatRange( 0.3, 2.0 );
|
||
if ( self.shootStyle == "full" || self.shootStyle == "burst" )
|
||
{
|
||
rate = animscripts\weaponList::autoShootAnimRate();
|
||
if ( rate > 1.999 )
|
||
{
|
||
rate = 1.999;
|
||
}
|
||
}
|
||
else if ( IsDefined( self.shootEnt ) && IsDefined( self.shootEnt.magic_bullet_shield ) )
|
||
{
|
||
rate = 0.25;
|
||
}
|
||
else if( is_rusher() && self.rusherType == "pistol" )
|
||
{
|
||
rate = 2.0;
|
||
}
|
||
if ( self usingBoltActionWeapon() )
|
||
{
|
||
rate = 1.0;
|
||
}
|
||
else if ( self usingGasWeapon() )
|
||
{
|
||
rate = 1.0;
|
||
}
|
||
else if ( self usingShotgun() )
|
||
{
|
||
rate = 1.0;
|
||
}
|
||
else if ( self usingRocketLauncher() )
|
||
{
|
||
rate = 1.0;
|
||
}
|
||
self SetFlaggedAnimKnobRestart( animName, fireAnim, 1, .2, rate );
|
||
self updatePlayerSightAccuracy();
|
||
FireUntilOutOfAmmoInternal( animName, fireAnim, stopOnAnimationEnd, maxshots );
|
||
self ClearAnim( %add_fire, .2 );
|
||
}
|
||
FireUntilOutOfAmmoInternal( animName, fireAnim, stopOnAnimationEnd, maxshots )
|
||
{
|
||
self endon("enemy");
|
||
if ( IsPlayer( self.enemy ) && (self.shootStyle == "full" || self.shootStyle == "semi") )
|
||
{
|
||
level endon("player_becoming_invulnerable");
|
||
}
|
||
if ( stopOnAnimationEnd )
|
||
{
|
||
self thread NotifyOnAnimEnd( animName, "fireAnimEnd" );
|
||
self endon( "fireAnimEnd" );
|
||
}
|
||
if ( !IsDefined( maxshots ) )
|
||
{
|
||
maxshots = -1;
|
||
}
|
||
numshots = 0;
|
||
hasFireNotetrack = animHasNoteTrack( fireAnim, "fire" );
|
||
usingRocketLauncher = (weaponClass( self.weapon ) == "rocketlauncher");
|
||
while(1)
|
||
{
|
||
if ( hasFireNotetrack )
|
||
{
|
||
if (self usingBoltActionWeapon() && numshots > 0)
|
||
{
|
||
break;
|
||
}
|
||
self waittillmatch( animName, "fire" );
|
||
if ( self usingBoltActionWeapon())
|
||
{
|
||
self.a.needsToRechamber = 1;
|
||
}
|
||
}
|
||
if ( numshots == maxshots )
|
||
{
|
||
break;
|
||
}
|
||
if ( !self.bulletsInClip )
|
||
{
|
||
if ( !cheatAmmoIfNecessary() )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
if ( aimedAtShootEntOrPos() && GetTime() > self.a.lastShootTime )
|
||
{
|
||
self shootAtShootEntOrPos();
|
||
assertex( self.bulletsInClip >= 0, self.bulletsInClip );
|
||
if ( IsPlayer( self.enemy ) && flag("player_is_invulnerable") )
|
||
{
|
||
if ( RandomInt(3) == 0 )
|
||
{
|
||
self.bulletsInClip--;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
self.bulletsInClip--;
|
||
}
|
||
if ( usingRocketLauncher )
|
||
{
|
||
self.a.rockets--;
|
||
if ( isSubStr(self.weapon, "rpg") )
|
||
{
|
||
self hidepart("tag_rocket");
|
||
self.a.rocketVisible = false;
|
||
}
|
||
}
|
||
}
|
||
numshots++;
|
||
self thread shotgunPumpSound( animName );
|
||
if ( self.fastBurst && numshots == maxshots )
|
||
{
|
||
break;
|
||
}
|
||
if ( !hasFireNotetrack )
|
||
{
|
||
self waittillmatch( animName, "end" );
|
||
}
|
||
if (self usingBoltActionWeapon () )
|
||
{
|
||
wait 0.5;
|
||
}
|
||
}
|
||
if ( stopOnAnimationEnd )
|
||
{
|
||
self notify( "fireAnimEnd" );
|
||
}
|
||
}
|
||
aimedAtShootEntOrPos()
|
||
{
|
||
tag_weapon = self gettagorigin("tag_weapon");
|
||
if ( !IsDefined(tag_weapon) )
|
||
{
|
||
return false;
|
||
}
|
||
if ( !IsDefined( self.shootPos ) )
|
||
{
|
||
assert( !IsDefined( self.shootEnt ) );
|
||
return true;
|
||
}
|
||
weaponAngles = self GetTagAngles("tag_weapon");
|
||
anglesToShootPos = VectorToAngles( self.shootPos - tag_weapon );
|
||
absyawdiff = AbsAngleClamp180( weaponAngles[1] - anglesToShootPos[1] );
|
||
if ( absyawdiff > self.aimThresholdYaw )
|
||
{
|
||
if ( DistanceSquared( self GetShootAtPos(), self.shootPos ) > 64*64 || absyawdiff > 45 )
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
return AbsAngleClamp180( weaponAngles[0] - anglesToShootPos[0] ) <= self.aimThresholdPitch;
|
||
}
|
||
NotifyOnAnimEnd( animNotify, endNotify )
|
||
{
|
||
self endon("killanimscript");
|
||
self endon( endNotify );
|
||
self waittillmatch( animNotify, "end" );
|
||
self notify( endNotify );
|
||
}
|
||
shootAtShootEntOrPos()
|
||
{
|
||
if( IsDefined( self.shoot_notify ) )
|
||
{
|
||
self notify( self.shoot_notify );
|
||
}
|
||
self shoot_notify_wrapper();
|
||
if ( IsDefined( self.shootEnt ) )
|
||
{
|
||
if ( IsDefined( self.enemy ) && self.shootEnt == self.enemy )
|
||
{
|
||
self shootEnemyWrapper();
|
||
}
|
||
}
|
||
else
|
||
{
|
||
assert( IsDefined( self.shootPos ) );
|
||
self shootPosWrapper( self.shootPos );
|
||
}
|
||
}
|
||
showRocket()
|
||
{
|
||
if ( !isSubStr(self.weapon, "rpg") )
|
||
{
|
||
return;
|
||
}
|
||
self.a.rocketVisible = true;
|
||
self showpart("tag_rocket");
|
||
self notify("showing_rocket");
|
||
}
|
||
showRocketWhenReloadIsDone()
|
||
{
|
||
if ( self.weapon != "rpg" )
|
||
{
|
||
return;
|
||
}
|
||
self endon("death");
|
||
self endon("showing_rocket");
|
||
self waittill("killanimscript");
|
||
self showRocket();
|
||
}
|
||
decrementBulletsInClip()
|
||
{
|
||
if ( self.bulletsInClip )
|
||
{
|
||
self.bulletsInClip--;
|
||
}
|
||
}
|
||
shotgunPumpSound( animName )
|
||
{
|
||
if ( !self usingShotgun() )
|
||
{
|
||
return;
|
||
}
|
||
self endon("killanimscript");
|
||
self notify("shotgun_pump_sound_end");
|
||
self endon("shotgun_pump_sound_end");
|
||
self thread stopShotgunPumpAfterTime( 2.0 );
|
||
self waittillmatch( animName, "rechamber" );
|
||
self PlaySound( "wpn_shotgun_pump" );
|
||
self notify("shotgun_pump_sound_end");
|
||
}
|
||
stopShotgunPumpAfterTime( timer )
|
||
{
|
||
self endon("killanimscript");
|
||
self endon("shotgun_pump_sound_end");
|
||
wait timer;
|
||
self notify("shotgun_pump_sound_end");
|
||
}
|
||
NeedToReload( thresholdFraction )
|
||
{
|
||
if ( IsDefined( self.noreload ) )
|
||
{
|
||
assertex( self.noreload, ".noreload must be true or undefined" );
|
||
if ( self.bulletsinclip < weaponClipSize( self.weapon ) * 0.5 )
|
||
{
|
||
self.bulletsinclip = int( weaponClipSize( self.weapon ) * 0.5 );
|
||
}
|
||
return false;
|
||
}
|
||
if ( self.weapon == "none" )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self.bulletsInClip <= weaponClipSize( self.weapon ) * thresholdFraction )
|
||
{
|
||
if ( thresholdFraction == 0 )
|
||
{
|
||
if ( cheatAmmoIfNecessary() )
|
||
{
|
||
return false;
|
||
}
|
||
}
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
putGunBackInHandOnKillAnimScript()
|
||
{
|
||
self endon ( "weapon_switch_done" );
|
||
self endon ( "death" );
|
||
self notify( "put gun back in hand end unique" );
|
||
self endon( "put gun back in hand end unique" );
|
||
self waittill( "killanimscript" );
|
||
animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
|
||
}
|
||
Reload( thresholdFraction, optionalAnimation )
|
||
{
|
||
if( self usingGasWeapon() )
|
||
{
|
||
return flamethrower_reload();
|
||
}
|
||
self endon("killanimscript");
|
||
if ( !NeedToReload( thresholdFraction ) )
|
||
{
|
||
return false;
|
||
}
|
||
self.a.Alertness = "casual";
|
||
self animscripts\battleChatter_ai::evaluateReloadEvent();
|
||
self maps\_dds::dds_notify_reload( undefined, ( self.team == "allies" ) );
|
||
if ( IsDefined( optionalAnimation ) )
|
||
{
|
||
self ClearAnim( %body, .1 );
|
||
self SetFlaggedAnimKnobAll( "reloadanim", optionalAnimation, %body, 1, .1, 1 );
|
||
animscripts\shared::DoNoteTracks( "reloadanim" );
|
||
self animscripts\weaponList::RefillClip();
|
||
}
|
||
else
|
||
{
|
||
if (self.a.pose == "prone")
|
||
{
|
||
self SetFlaggedAnimKnobAll("reloadanim", animArrayPickRandom("reload"), %body, 1, .1, 1);
|
||
self UpdateProne(%prone_legs_up, %prone_legs_down, 1, 0.1, 1);
|
||
}
|
||
else
|
||
{
|
||
println ("Bad anim_pose in combat::Reload");
|
||
wait 2;
|
||
return;
|
||
}
|
||
animscripts\shared::DoNoteTracks("reloadanim");
|
||
animscripts\weaponList::RefillClip();
|
||
self ClearAnim(%upperbody, .1);
|
||
}
|
||
return true;
|
||
}
|
||
flamethrower_reload()
|
||
{
|
||
wait( 0.05 );
|
||
self animscripts\weaponList::RefillClip();
|
||
return true;
|
||
}
|
||
getGrenadeThrowOffset( throwAnim )
|
||
{
|
||
offset = (0, 0, 64);
|
||
if ( IsDefined( throwAnim ) )
|
||
{
|
||
if ( throwAnim == %exposed_grenadethrowb ) offset = (41.5391, 7.28883, 72.2128);
|
||
else if ( throwAnim == %exposed_grenadethrowc ) offset = (34.8849, -4.77048, 74.0488);
|
||
else if ( throwAnim == %exposed_grenadethrowb ) offset = (41.5391, 7.28883, 72.2128);
|
||
else if ( throwAnim == %exposed_grenadethrowc ) offset = (34.8849, -4.77048, 74.0488);
|
||
else if ( throwAnim == %corner_standl_grenade_a ) offset = (41.605, 6.80107, 81.4785);
|
||
else if ( throwAnim == %corner_standl_grenade_b ) offset = (24.1585, -14.7221, 29.2992);
|
||
else if ( throwAnim == %cornercrl_grenadea ) offset = (25.8988, -10.2811, 30.4813);
|
||
else if ( throwAnim == %cornercrl_grenadeb ) offset = (24.688, 45.0702, 64.377);
|
||
else if ( throwAnim == %corner_standr_grenade_a ) offset = (37.1254, -32.7053, 76.5745);
|
||
else if ( throwAnim == %corner_standr_grenade_b ) offset = (19.356, 15.5341, 16.5036);
|
||
else if ( throwAnim == %cornercrr_grenadea ) offset = (39.8857, 5.92472, 24.5878);
|
||
else if ( throwAnim == %covercrouch_grenadea ) offset = (-1.6363, -0.693674, 60.1009);
|
||
else if ( throwAnim == %covercrouch_grenadeb ) offset = (-1.6363, -0.693674, 60.1009);
|
||
else if ( throwAnim == %coverstand_grenadea ) offset = (10.8573, 7.12614, 77.2356);
|
||
else if ( throwAnim == %coverstand_grenadeb ) offset = (19.1804, 5.68214, 73.2278);
|
||
else if ( throwAnim == %prone_grenade_a ) offset = (12.2859, -1.3019, 33.4307);
|
||
else if ( throwAnim == %ai_pillar_stand_grenade_throw_01 ) offset = (3.33533, 25.1428, 33.6935);
|
||
else if ( throwAnim == %ai_pillar_stand_grenade_throw_02 ) offset = (15.8536, -12.6112, 66.6897);
|
||
else if ( throwAnim == %ai_pillar_stand_grenade_throw_03 ) offset = (25.7513, -19.2158, 23.2601);
|
||
else if ( throwAnim == %ai_pillar_crouch_grenade_throw_01 ) offset = (13.3738, -22.7841, 44.6094);
|
||
else if ( throwAnim == %ai_pillar_crouch_grenade_throw_02 ) offset = (19.3524, -16.1327, 18.6373);
|
||
else if ( throwAnim == %ai_pillar_crouch_grenade_throw_03 ) offset = (18.614, 19.1907, 15.9741);
|
||
}
|
||
if ( offset[2] == 64 )
|
||
{
|
||
if ( IsDefined( throwAnim ) )
|
||
{
|
||
println( "^1Warning: undefined grenade throw animation used; hand offset unknown" );
|
||
}
|
||
else
|
||
{
|
||
println( "^1Warning: grenade throw animation ", throwAnim, " has no recorded hand offset" );
|
||
}
|
||
}
|
||
return offset;
|
||
}
|
||
ThrowGrenadeAtPlayerASAP_combat_utility()
|
||
{
|
||
if ( anim.numGrenadesInProgressTowardsPlayer == 0 )
|
||
{
|
||
anim.grenadeTimers["player_fraggrenade"] = 0;
|
||
anim.grenadeTimers["player_flash_grenade"] = 0;
|
||
}
|
||
anim.throwGrenadeAtPlayerASAP = true;
|
||
}
|
||
setActiveGrenadeTimer( throwingAt )
|
||
{
|
||
if ( IsPlayer( throwingAt ) )
|
||
{
|
||
self.activeGrenadeTimer = "player_" + self.grenadeWeapon;
|
||
}
|
||
else
|
||
{
|
||
self.activeGrenadeTimer = "AI_" + self.grenadeWeapon;
|
||
}
|
||
if( !IsDefined(anim.grenadeTimers[self.activeGrenadeTimer]) )
|
||
{
|
||
anim.grenadeTimers[self.activeGrenadeTimer] = randomIntRange( 1000, 20000 );
|
||
}
|
||
}
|
||
considerChangingTarget( throwingAt )
|
||
{
|
||
if ( !IsPlayer( throwingAt ) && self.team == "axis" )
|
||
{
|
||
players = GetPlayers();
|
||
for( i = 0; i < players.size; i++ )
|
||
{
|
||
player = players[i];
|
||
if ( GetTime() < anim.grenadeTimers[self.activeGrenadeTimer] )
|
||
{
|
||
if ( player.ignoreme )
|
||
{
|
||
return throwingAt;
|
||
}
|
||
myGroup = self getthreatbiasgroup();
|
||
playerGroup = player getthreatbiasgroup();
|
||
if ( myGroup != "" && playerGroup != "" && getThreatBias( playerGroup, myGroup ) < -10000 )
|
||
{
|
||
return throwingAt;
|
||
}
|
||
if ( self canSee( player ) || (isAI( throwingAt ) && throwingAt canSee( player )) )
|
||
{
|
||
if ( IsDefined( self.covernode ) )
|
||
{
|
||
angles = VectorToAngles( player.origin - self.origin );
|
||
yawDiff = AngleClamp180( self.covernode.angles[1] - angles[1] );
|
||
}
|
||
else
|
||
{
|
||
yawDiff = self GetYawToSpot( player.origin );
|
||
}
|
||
if ( abs( yawDiff ) < 60 )
|
||
{
|
||
throwingAt = player;
|
||
self setActiveGrenadeTimer( throwingAt );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
return throwingAt;
|
||
}
|
||
usingPlayerGrenadeTimer()
|
||
{
|
||
return self.activeGrenadeTimer == "player_" + self.grenadeWeapon;
|
||
}
|
||
setGrenadeTimer( grenadeTimer, newValue )
|
||
{
|
||
oldValue = anim.grenadeTimers[ grenadeTimer ];
|
||
anim.grenadeTimers[ grenadeTimer ] = max( newValue, oldValue );
|
||
}
|
||
getDesiredGrenadeTimerValue()
|
||
{
|
||
nextGrenadeTimeToUse = undefined;
|
||
if ( self usingPlayerGrenadeTimer() )
|
||
{
|
||
nextGrenadeTimeToUse = GetTime() + anim.playerGrenadeBaseTime + RandomInt(anim.playerGrenadeRangeTime);
|
||
}
|
||
else
|
||
{
|
||
nextGrenadeTimeToUse = GetTime() + 40000 + RandomInt(60000);
|
||
}
|
||
return nextGrenadeTimeToUse;
|
||
}
|
||
mayThrowDoubleGrenade()
|
||
{
|
||
assert( self.activeGrenadeTimer == "player_fraggrenade" );
|
||
if ( player_died_recently() )
|
||
{
|
||
return false;
|
||
}
|
||
if ( !anim.double_grenades_allowed )
|
||
{
|
||
return false;
|
||
}
|
||
if ( GetTime() < anim.grenadeTimers[ "player_double_grenade" ] )
|
||
{
|
||
return false;
|
||
}
|
||
if ( GetTime() > anim.lastFragGrenadeToPlayerStart + 3000 )
|
||
{
|
||
return false;
|
||
}
|
||
return anim.numGrenadesInProgressTowardsPlayer < 2;
|
||
}
|
||
myGrenadeCoolDownElapsed()
|
||
{
|
||
if ( player_died_recently() )
|
||
{
|
||
return false;
|
||
}
|
||
return ( GetTime() >= self.a.nextGrenadeTryTime );
|
||
}
|
||
grenadeCoolDownElapsed()
|
||
{
|
||
if (self.script_forcegrenade == 1)
|
||
{
|
||
return true;
|
||
}
|
||
if ( !myGrenadeCoolDownElapsed() )
|
||
{
|
||
return false;
|
||
}
|
||
if ( GetTime() >= anim.grenadeTimers[self.activeGrenadeTimer] )
|
||
{
|
||
return true;
|
||
}
|
||
if ( self.activeGrenadeTimer == "player_fraggrenade" )
|
||
{
|
||
return mayThrowDoubleGrenade();
|
||
}
|
||
return false;
|
||
}
|
||
isGrenadePosSafe( throwingAt, destination )
|
||
{
|
||
if ( IsDefined( anim.throwGrenadeAtPlayerASAP ) && self usingPlayerGrenadeTimer() )
|
||
{
|
||
return true;
|
||
}
|
||
distanceThreshold = 200;
|
||
if ( self.grenadeWeapon == "flash_grenade" )
|
||
{
|
||
distanceThreshold = 512;
|
||
}
|
||
distanceThresholdSq = distanceThreshold * distanceThreshold;
|
||
closest = undefined;
|
||
closestdist = 100000000;
|
||
secondclosest = undefined;
|
||
secondclosestdist = 100000000;
|
||
for ( i = 0; i < self.squad.members.size; i++ )
|
||
{
|
||
if ( !IsAlive( self.squad.members[i] ) )
|
||
{
|
||
continue;
|
||
}
|
||
dist = DistanceSquared( self.squad.members[i].origin, destination );
|
||
if ( dist > distanceThresholdSq )
|
||
{
|
||
continue;
|
||
}
|
||
if ( dist < closestdist )
|
||
{
|
||
secondclosestdist = closestdist;
|
||
secondclosest = closest;
|
||
closestdist = dist;
|
||
closest = self.squad.members[i];
|
||
}
|
||
else if ( dist < secondclosestdist )
|
||
{
|
||
secondclosestdist = dist;
|
||
secondclosest = self.squad.members[i];
|
||
}
|
||
}
|
||
if ( IsDefined( closest ) && sightTracePassed( closest getEye(), destination, false, undefined ) )
|
||
{
|
||
return false;
|
||
}
|
||
if ( IsDefined( secondclosest ) && sightTracePassed( closest getEye(), destination, false, undefined ) )
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
TryGrenadePosProc( throwingAt, destination, optionalAnimation, armOffset )
|
||
{
|
||
if ( !isGrenadePosSafe( throwingAt, destination ) )
|
||
{
|
||
return false;
|
||
}
|
||
else if ( DistanceSquared( self.origin, destination ) < 200 * 200 )
|
||
{
|
||
return false;
|
||
}
|
||
trace = PhysicsTrace( destination + (0,0,1), destination + (0,0,-500) );
|
||
if ( trace == destination + (0,0,-500) )
|
||
{
|
||
return false;
|
||
}
|
||
trace += (0,0,.1);
|
||
return TryGrenadeThrow( throwingAt, trace, optionalAnimation, armOffset );
|
||
}
|
||
TryGrenade( throwingAt, optionalAnimation )
|
||
{
|
||
if( self usingGasWeapon() )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self.weapon=="mg42" || self.grenadeammo <= 0 )
|
||
{
|
||
return false;
|
||
}
|
||
self setActiveGrenadeTimer( throwingAt );
|
||
throwingAt = considerChangingTarget( throwingAt );
|
||
if ( !grenadeCoolDownElapsed() )
|
||
{
|
||
return false;
|
||
}
|
||
armOffset = getGrenadeThrowOffset( optionalAnimation );
|
||
if ( IsDefined( self.enemy ) && throwingAt == self.enemy )
|
||
{
|
||
if ( self.grenadeWeapon == "flash_grenade" && !shouldThrowFlashBangAtEnemy() )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self canSeeEnemyFromExposed() )
|
||
{
|
||
if ( !isGrenadePosSafe( throwingAt, throwingAt.origin ) )
|
||
{
|
||
return false;
|
||
}
|
||
return TryGrenadeThrow( throwingAt, undefined, optionalAnimation, armOffset );
|
||
}
|
||
else if ( self canSuppressEnemyFromExposed() )
|
||
{
|
||
return TryGrenadePosProc( throwingAt, self getEnemySightPos(), optionalAnimation, armOffset );
|
||
}
|
||
else
|
||
{
|
||
if ( !isGrenadePosSafe( throwingAt, throwingAt.origin ) )
|
||
{
|
||
return false;
|
||
}
|
||
return TryGrenadeThrow( throwingAt, undefined, optionalAnimation, armOffset );
|
||
}
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
return TryGrenadePosProc( throwingAt, throwingAt.origin, optionalAnimation, armOffset );
|
||
}
|
||
}
|
||
TryGrenadeThrow( throwingAt, destination, optionalAnimation, armOffset )
|
||
{
|
||
if( self usingGasWeapon() )
|
||
{
|
||
return false;
|
||
}
|
||
if ( GetTime() < 10000 )
|
||
{
|
||
return false;
|
||
}
|
||
if (IsDefined(optionalAnimation))
|
||
{
|
||
throw_anim = optionalAnimation;
|
||
gunHand = self.a.gunHand;
|
||
}
|
||
else
|
||
{
|
||
switch (self.a.special)
|
||
{
|
||
case "cover_crouch":
|
||
case "none":
|
||
if (self.a.pose == "stand")
|
||
{
|
||
armOffset = (0,0,80);
|
||
throw_anim = animArray("grenade_throw");
|
||
}
|
||
else
|
||
{
|
||
armOffset = (0,0,65);
|
||
throw_anim = animArray("grenade_throw");
|
||
}
|
||
gunHand = "left";
|
||
break;
|
||
default:
|
||
throw_anim = undefined;
|
||
gunHand = undefined;
|
||
break;
|
||
}
|
||
}
|
||
if (!IsDefined(throw_anim))
|
||
{
|
||
return (false);
|
||
}
|
||
if (IsDefined (destination))
|
||
{
|
||
throwvel = self checkGrenadeThrowPos(armOffset, "min energy", destination);
|
||
if (!IsDefined(throwvel))
|
||
{
|
||
throwvel = self checkGrenadeThrowPos(armOffset, "min time", destination);
|
||
}
|
||
if (!IsDefined(throwvel))
|
||
{
|
||
throwvel = self checkGrenadeThrowPos(armOffset, "max time", destination);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
throwvel = self checkGrenadeThrow(armOffset, "min energy", self.randomGrenadeRange);
|
||
if (!IsDefined(throwvel))
|
||
{
|
||
throwvel = self checkGrenadeThrow(armOffset, "min time", self.randomGrenadeRange);
|
||
}
|
||
if (!IsDefined(throwvel))
|
||
{
|
||
throwvel = self checkGrenadeThrow(armOffset, "max time", self.randomGrenadeRange);
|
||
}
|
||
}
|
||
self.a.nextGrenadeTryTime = GetTime() + randomintrange(1000,2000);
|
||
if ( IsDefined(throwvel) )
|
||
{
|
||
if (!IsDefined(self.oldGrenAwareness))
|
||
{
|
||
self.oldGrenAwareness = self.grenadeawareness;
|
||
}
|
||
self.grenadeawareness = 0;
|
||
nextGrenadeTimeToUse = self getDesiredGrenadeTimerValue();
|
||
setGrenadeTimer( self.activeGrenadeTimer, min( GetTime() + 3000, nextGrenadeTimeToUse ) );
|
||
secondGrenadeOfDouble = false;
|
||
if ( self usingPlayerGrenadeTimer() )
|
||
{
|
||
anim.numGrenadesInProgressTowardsPlayer++;
|
||
self thread reduceGIPTPOnKillanimscript();
|
||
if ( anim.numGrenadesInProgressTowardsPlayer > 1 )
|
||
{
|
||
secondGrenadeOfDouble = true;
|
||
}
|
||
}
|
||
if ( self.activeGrenadeTimer == "player_fraggrenade" && anim.numGrenadesInProgressTowardsPlayer <= 1 )
|
||
{
|
||
anim.lastFragGrenadeToPlayerStart = GetTime();
|
||
}
|
||
DoGrenadeThrow( throw_anim, nextGrenadeTimeToUse, secondGrenadeOfDouble );
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
}
|
||
return false;
|
||
}
|
||
reduceGIPTPOnKillanimscript()
|
||
{
|
||
self endon("dont_reduce_giptp_on_killanimscript");
|
||
self waittill("killanimscript");
|
||
anim.numGrenadesInProgressTowardsPlayer--;
|
||
}
|
||
DoGrenadeThrow( throw_anim, nextGrenadeTimeToUse, secondGrenadeOfDouble )
|
||
{
|
||
self animscripts\battleChatter_ai::evaluateAttackEvent("grenade");
|
||
self notify ("stop_aiming_at_enemy");
|
||
self SetFlaggedAnimKnobAllRestart("throwanim", throw_anim, %body, 1, 0.1, 1);
|
||
self thread animscripts\shared::DoNoteTracksForever("throwanim", "killanimscript");
|
||
model = getGrenadeModel();
|
||
attachside = "none";
|
||
for (;;)
|
||
{
|
||
self waittill("throwanim", notetrack);
|
||
if ( notetrack == "grenade_left" || notetrack == "grenade_right" )
|
||
{
|
||
attachside = attachGrenadeModel(model, "TAG_INHAND");
|
||
self.isHoldingGrenade = true;
|
||
}
|
||
if ( notetrack == "grenade_throw" || notetrack == "grenade throw" )
|
||
{
|
||
break;
|
||
}
|
||
assert(notetrack != "end");
|
||
if ( notetrack == "end" )
|
||
{
|
||
anim.numGrenadesInProgressTowardsPlayer--;
|
||
self notify("dont_reduce_giptp_on_killanimscript");
|
||
return false;
|
||
}
|
||
}
|
||
self notify("dont_reduce_giptp_on_killanimscript");
|
||
if ( self usingPlayerGrenadeTimer() )
|
||
{
|
||
self thread watchGrenadeTowardsPlayer( nextGrenadeTimeToUse );
|
||
}
|
||
self maps\_dds::dds_notify_grenade( self.grenadeweapon, ( self.team == "allies" ), false );
|
||
self throwGrenade();
|
||
if ( !self usingPlayerGrenadeTimer() )
|
||
{
|
||
setGrenadeTimer( self.activeGrenadeTimer, nextGrenadeTimeToUse );
|
||
}
|
||
if ( secondGrenadeOfDouble )
|
||
{
|
||
if ( anim.numGrenadesInProgressTowardsPlayer > 1 || GetTime() - anim.lastGrenadeLandedNearPlayerTime < 2000 )
|
||
{
|
||
anim.grenadeTimers["player_double_grenade"] = GetTime() + min( 5000, anim.playerDoubleGrenadeTime );
|
||
}
|
||
}
|
||
self notify ("stop grenade check");
|
||
if ( attachSide != "none" )
|
||
{
|
||
self detach(model, attachside);
|
||
}
|
||
else
|
||
{
|
||
print ("No grenade hand set: ");
|
||
println (throw_anim);
|
||
println("animation in console does not specify grenade hand");
|
||
}
|
||
self.isHoldingGrenade = undefined;
|
||
self.grenadeawareness = self.oldGrenAwareness;
|
||
self.oldGrenAwareness = undefined;
|
||
self waittillmatch("throwanim", "end");
|
||
self SetAnim(%exposed_modern,1,.2);
|
||
self SetAnim(%exposed_aiming,1);
|
||
self ClearAnim(throw_anim,.2);
|
||
}
|
||
watchGrenadeTowardsPlayer( nextGrenadeTimeToUse )
|
||
{
|
||
watchGrenadeTowardsPlayerInternal( nextGrenadeTimeToUse );
|
||
anim.numGrenadesInProgressTowardsPlayer--;
|
||
}
|
||
watchGrenadeTowardsPlayerInternal( nextGrenadeTimeToUse )
|
||
{
|
||
activeGrenadeTimer = self.activeGrenadeTimer;
|
||
timeoutObj = SpawnStruct();
|
||
timeoutObj thread watchGrenadeTowardsPlayerTimeout( 5 );
|
||
timeoutObj endon("watchGrenadeTowardsPlayerTimeout");
|
||
type = self.grenadeWeapon;
|
||
grenade = self getGrenadeIThrew();
|
||
if ( !IsDefined( grenade ) )
|
||
{
|
||
return;
|
||
}
|
||
setGrenadeTimer( activeGrenadeTimer, min( GetTime() + 5000, nextGrenadeTimeToUse ) );
|
||
goodRadiusSqrd = 250 * 250;
|
||
giveUpRadiusSqrd = 400 * 400;
|
||
if ( type == "flash_grenade" )
|
||
{
|
||
goodRadiusSqrd = 900 * 900;
|
||
giveUpRadiusSqrd = 1300 * 1300;
|
||
}
|
||
players = GetPlayers();
|
||
prevorigin = grenade.origin;
|
||
while(1)
|
||
{
|
||
wait .1;
|
||
if ( !IsDefined( grenade ) )
|
||
{
|
||
break;
|
||
}
|
||
if ( grenade.origin == prevorigin )
|
||
{
|
||
if ( DistanceSquared( grenade.origin, players[0].origin ) < goodRadiusSqrd || DistanceSquared( grenade.origin, players[0].origin ) > giveUpRadiusSqrd )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
prevorigin = grenade.origin;
|
||
}
|
||
grenadeorigin = prevorigin;
|
||
if ( IsDefined( grenade ) )
|
||
{
|
||
grenadeorigin = grenade.origin;
|
||
}
|
||
if ( DistanceSquared( grenadeorigin, players[0].origin ) < goodRadiusSqrd )
|
||
{
|
||
level notify("threw_grenade_at_player");
|
||
anim.throwGrenadeAtPlayerASAP = undefined;
|
||
if ( GetTime() - anim.lastGrenadeLandedNearPlayerTime < 3000 )
|
||
{
|
||
anim.grenadeTimers["player_double_grenade"] = GetTime() + anim.playerDoubleGrenadeTime;
|
||
}
|
||
anim.lastGrenadeLandedNearPlayerTime = GetTime();
|
||
setGrenadeTimer( activeGrenadeTimer, nextGrenadeTimeToUse );
|
||
}
|
||
else
|
||
{
|
||
}
|
||
}
|
||
getGrenadeIThrew()
|
||
{
|
||
self endon("killanimscript");
|
||
self waittill( "grenade_fire", grenade );
|
||
return grenade;
|
||
}
|
||
watchGrenadeTowardsPlayerTimeout( timerlength )
|
||
{
|
||
wait timerlength;
|
||
self notify("watchGrenadeTowardsPlayerTimeout");
|
||
}
|
||
attachGrenadeModel(model, tag)
|
||
{
|
||
self attach (model, tag);
|
||
thread detachGrenadeOnScriptChange(model, tag);
|
||
return tag;
|
||
}
|
||
detachGrenadeOnScriptChange(model, tag)
|
||
{
|
||
self endon ("stop grenade check");
|
||
self waittill ("killanimscript");
|
||
if ( !IsDefined( self ) )
|
||
{
|
||
return;
|
||
}
|
||
if (IsDefined(self.oldGrenAwareness))
|
||
{
|
||
self.grenadeawareness = self.oldGrenAwareness;
|
||
self.oldGrenAwareness = undefined;
|
||
}
|
||
self detach(model, tag);
|
||
}
|
||
offsetToOrigin(start)
|
||
{
|
||
forward = AnglesToForward(self.angles);
|
||
right = AnglesToRight(self.angles);
|
||
up = anglestoup(self.angles);
|
||
forward = vector_scale (forward, start[0]);
|
||
right = vector_scale (right, start[1]);
|
||
up = vector_scale (up, start[2]);
|
||
return (forward + right + up);
|
||
}
|
||
grenadeLine(start, end)
|
||
{
|
||
level notify ("armoffset");
|
||
level endon ("armoffset");
|
||
start = self.origin + offsetToOrigin(start);
|
||
for (;;)
|
||
{
|
||
line (start, end, (1,0,1));
|
||
Print3d (start, start, (0.2,0.5,1.0), 1, 1);
|
||
Print3d (end, end, (0.2,0.5,1.0), 1, 1);
|
||
wait (0.05);
|
||
}
|
||
}
|
||
getGrenadeDropVelocity()
|
||
{
|
||
yaw = RandomFloat( 360 );
|
||
pitch = RandomFloatRange( 30, 75 );
|
||
amntz = sin( pitch );
|
||
cospitch = cos( pitch );
|
||
amntx = cos( yaw ) * cospitch;
|
||
amnty = sin( yaw ) * cospitch;
|
||
speed = RandomFloatRange( 100, 200 );
|
||
velocity = (amntx, amnty, amntz) * speed;
|
||
return velocity;
|
||
}
|
||
dropGrenade()
|
||
{
|
||
grenadeOrigin = self GetTagOrigin ( "tag_inhand" );
|
||
velocity = getGrenadeDropVelocity();
|
||
self MagicGrenadeManual( grenadeOrigin, velocity, 3 );
|
||
}
|
||
EyesAtEnemy()
|
||
{
|
||
self notify ("stop EyesAtEnemy internal");
|
||
self endon ("death");
|
||
self endon ("stop EyesAtEnemy internal");
|
||
for (;;)
|
||
{
|
||
if (IsDefined(self.enemy))
|
||
{
|
||
}
|
||
wait 2;
|
||
}
|
||
}
|
||
FindCoverNearSelf()
|
||
{
|
||
oldKeepNodeInGoal = self.keepClaimedNodeInGoal;
|
||
oldKeepNode = self.keepClaimedNode;
|
||
self.keepClaimedNodeInGoal = false;
|
||
self.keepClaimedNode = false;
|
||
node = self FindBestCoverNode();
|
||
if ( IsDefined( node ) )
|
||
{
|
||
if ( self.a.script != "combat" )
|
||
{
|
||
if ( self UseCoverNode( node ) )
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
}
|
||
}
|
||
}
|
||
self.keepClaimedNodeInGoal = oldKeepNodeInGoal;
|
||
self.keepClaimedNode = oldKeepNode;
|
||
return false;
|
||
}
|
||
lookForBetterCover()
|
||
{
|
||
if ( !isValidEnemy( self.enemy ) )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self.fixedNode )
|
||
{
|
||
return false;
|
||
}
|
||
node = self getBestCoverNodeIfAvailable();
|
||
if ( IsDefined( node ) )
|
||
{
|
||
return useCoverNodeIfPossible( node );
|
||
}
|
||
return false;
|
||
}
|
||
getBestCoverNodeIfAvailable()
|
||
{
|
||
node = self FindBestCoverNode();
|
||
if ( !IsDefined(node) )
|
||
{
|
||
return undefined;
|
||
}
|
||
currentNode = self GetClaimedNode();
|
||
if ( IsDefined( currentNode ) && node == currentNode )
|
||
{
|
||
return undefined;
|
||
}
|
||
if ( IsDefined( self.coverNode ) && node == self.coverNode )
|
||
{
|
||
return undefined;
|
||
}
|
||
return node;
|
||
}
|
||
useCoverNodeIfPossible( node )
|
||
{
|
||
oldKeepNodeInGoal = self.keepClaimedNodeInGoal;
|
||
oldKeepNode = self.keepClaimedNode;
|
||
self.keepClaimedNodeInGoal = false;
|
||
self.keepClaimedNode = false;
|
||
if ( self UseCoverNode( node ) )
|
||
{
|
||
return true;
|
||
}
|
||
else
|
||
{
|
||
}
|
||
self.keepClaimedNodeInGoal = oldKeepNodeInGoal;
|
||
self.keepClaimedNode = oldKeepNode;
|
||
return false;
|
||
}
|
||
tryRunningToEnemy( ignoreSuppression )
|
||
{
|
||
if ( !isValidEnemy( self.enemy ) )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self.fixedNode )
|
||
{
|
||
return false;
|
||
}
|
||
if ( self IsInGoal( self.enemy.origin ) )
|
||
{
|
||
self FindReacquireDirectPath( ignoreSuppression );
|
||
}
|
||
else
|
||
{
|
||
self FindReacquireProximatePath( ignoreSuppression );
|
||
}
|
||
if ( self ReacquireMove() )
|
||
{
|
||
self.keepClaimedNodeInGoal = false;
|
||
self.keepClaimedNode = false;
|
||
self.a.magicReloadWhenReachEnemy = true;
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
getGunYawToShootEntOrPos()
|
||
{
|
||
if ( !IsDefined( self.shootPos ) )
|
||
{
|
||
assert( !IsDefined( self.shootEnt ) );
|
||
return 0;
|
||
}
|
||
yaw = self GetTagAngles("tag_weapon")[1] - GetYaw( self.shootPos );
|
||
yaw = AngleClamp180( yaw );
|
||
return yaw;
|
||
}
|
||
getGunPitchToShootEntOrPos()
|
||
{
|
||
if ( !IsDefined( self.shootPos ) )
|
||
{
|
||
assert( !IsDefined( self.shootEnt ) );
|
||
return 0;
|
||
}
|
||
pitch = self GetTagAngles("tag_weapon")[0] - VectorToAngles( self.shootPos - self gettagorigin("tag_weapon") )[0];
|
||
pitch = AngleClamp180( pitch );
|
||
return pitch;
|
||
}
|
||
getPitchToEnemy()
|
||
{
|
||
if(!IsDefined(self.enemy))
|
||
{
|
||
return 0;
|
||
}
|
||
vectorToEnemy = self.enemy GetShootAtPos() - self GetShootAtPos();
|
||
vectorToEnemy = VectorNormalize(vectortoenemy);
|
||
pitchDelta = 360 - VectorToAngles(vectorToEnemy)[0];
|
||
return AngleClamp180( pitchDelta );
|
||
}
|
||
getPitchToSpot(spot)
|
||
{
|
||
if(!IsDefined(spot))
|
||
{
|
||
return 0;
|
||
}
|
||
vectorToEnemy = spot - self GetShootAtPos();
|
||
vectorToEnemy = VectorNormalize(vectortoenemy);
|
||
pitchDelta = 360 - VectorToAngles(vectorToEnemy)[0];
|
||
return AngleClamp180( pitchDelta );
|
||
}
|
||
anim_set_next_move_to_new_cover()
|
||
{
|
||
self.a.next_move_to_new_cover = randomintrange( 1, 4 );
|
||
}
|
||
watchReloading()
|
||
{
|
||
self.isreloading = false;
|
||
while(1)
|
||
{
|
||
self waittill("reload_start");
|
||
self maps\_dds::dds_notify_reload( self GetCurrentWeapon(), ( self.team == "allies" ) );
|
||
self.isreloading = true;
|
||
self waittillreloadfinished();
|
||
self.isreloading = false;
|
||
}
|
||
}
|
||
waittillReloadFinished()
|
||
{
|
||
self thread timedNotify( 4, "reloadtimeout" );
|
||
self endon("reloadtimeout");
|
||
while(1)
|
||
{
|
||
self waittill("reload");
|
||
weap = self getCurrentWeapon();
|
||
if ( weap == "none" )
|
||
{
|
||
break;
|
||
}
|
||
if ( self getCurrentWeaponClipAmmo() >= weaponClipSize( weap ) )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
self notify("reloadtimeout");
|
||
}
|
||
timedNotify( time, msg )
|
||
{
|
||
self endon( msg );
|
||
wait time;
|
||
self notify( msg );
|
||
}
|
||
attackEnemyWhenFlashed()
|
||
{
|
||
self endon("killanimscript");
|
||
while(1)
|
||
{
|
||
if ( !IsDefined( self.enemy ) || !IsAlive( self.enemy ) || !IsSentient( self.enemy ) )
|
||
{
|
||
self waittill("enemy");
|
||
continue;
|
||
}
|
||
attackSpecificEnemyWhenFlashed();
|
||
}
|
||
}
|
||
attackSpecificEnemyWhenFlashed()
|
||
{
|
||
self endon("enemy");
|
||
self.enemy endon("death");
|
||
if ( IsDefined( self.enemy.flashendtime ) && GetTime() < self.enemy.flashendtime )
|
||
{
|
||
tryToAttackFlashedEnemy();
|
||
}
|
||
while ( 1 )
|
||
{
|
||
self.enemy waittill("flashed");
|
||
tryToAttackFlashedEnemy();
|
||
}
|
||
}
|
||
tryToAttackFlashedEnemy()
|
||
{
|
||
if ( self.enemy.flashingTeam != self.team )
|
||
{
|
||
return;
|
||
}
|
||
if ( DistanceSquared( self.origin, self.enemy.origin ) > 1024*1024 )
|
||
{
|
||
return;
|
||
}
|
||
while ( GetTime() < self.enemy.flashendtime - 500 )
|
||
{
|
||
if ( !self cansee( self.enemy ) && DistanceSquared( self.origin, self.enemy.origin ) < 800*800 )
|
||
{
|
||
tryRunningToEnemy( true );
|
||
}
|
||
wait .05;
|
||
}
|
||
}
|
||
shouldThrowFlashBangAtEnemy()
|
||
{
|
||
if ( DistanceSquared( self.origin, self.enemy.origin ) > 768 * 768 )
|
||
{
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
startFlashBanged()
|
||
{
|
||
if ( IsDefined( self.flashduration ) )
|
||
{
|
||
duration = self.flashduration;
|
||
}
|
||
else
|
||
{
|
||
duration = self getFlashBangedStrength() * 1000;
|
||
}
|
||
self.flashendtime = GetTime() + duration;
|
||
self notify("flashed");
|
||
return duration;
|
||
}
|
||
monitorFlash()
|
||
{
|
||
self endon("death");
|
||
self endon("stop_monitoring_flash");
|
||
while(1)
|
||
{
|
||
self waittill( "flashbang", amount_distance, amount_angle, attacker, attackerteam );
|
||
if ( self.flashbangImmunity )
|
||
{
|
||
continue;
|
||
}
|
||
if( IsDefined( self.script_immunetoflash ) && self.script_immunetoflash != 0 )
|
||
{
|
||
continue;
|
||
}
|
||
if ( IsDefined( self.team ) && IsDefined( attackerteam ) && self.team == attackerteam )
|
||
{
|
||
amount_distance = 3 * (amount_distance - .75);
|
||
if ( amount_distance < 0 )
|
||
{
|
||
continue;
|
||
}
|
||
}
|
||
minamountdist = 0.2;
|
||
if ( amount_distance > 1 - minamountdist )
|
||
{
|
||
amount_distance = 1.0;
|
||
}
|
||
else
|
||
{
|
||
amount_distance = amount_distance / (1 - minamountdist);
|
||
}
|
||
duration = 4.5 * amount_distance;
|
||
if ( duration < 0.25 )
|
||
{
|
||
continue;
|
||
}
|
||
self.flashingTeam = attackerteam;
|
||
self SetFlashBanged( true, duration );
|
||
self notify( "doFlashBanged", attacker );
|
||
}
|
||
}
|
||
isSniper()
|
||
{
|
||
return self.isSniper;
|
||
}
|
||
isSniperRifle( weapon )
|
||
{
|
||
return WeaponClass(weapon) == "rifle" && WeaponIsSemiAuto(weapon) && WeaponFireTime(weapon) > 0.2;
|
||
}
|
||
isCrossbow( weapon )
|
||
{
|
||
return ( IsSubstr(weapon, "crossbow") && !IsSubstr(weapon, "explosive") );
|
||
}
|
||
NeedToRechamber( )
|
||
{
|
||
if ( self usingBoltActionWeapon() && self.bulletsInClip && self.a.needsToRechamber )
|
||
{
|
||
return true;
|
||
}
|
||
return false;
|
||
}
|
||
getShootAnimPrefix()
|
||
{
|
||
if( self.a.script == "cover_left" || self.a.script == "cover_right" || self.a.script == "cover_pillar" )
|
||
{
|
||
if( IsDefined(self.cornerAiming) && self.cornerAiming && IsDefined(self.a.cornerMode) && self.a.cornerMode == "lean" )
|
||
{
|
||
return "lean_";
|
||
}
|
||
}
|
||
return "";
|
||
} |