IL-GSC/BO1/PC/ZM/animscripts/shared.gsc
2024-02-18 17:32:07 -05:00

1948 lines
49 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include maps\_utility;
#include animscripts\utility;
#include animscripts\combat_utility;
#include animscripts\anims;
#include common_scripts\utility;
#using_animtree ("generic_human");
placeWeaponOn( weapon, position )
{
self notify("weapon_position_change");
if (!IsDefined(self.weaponInfo[weapon]))
{
self call_overloaded_func( "animscripts\init", "initWeapon", weapon );
}
curPosition = self.weaponInfo[weapon].position;
assert( curPosition == "none" || self.a.weaponPos[curPosition] == weapon );
if ( position != "none" && self.a.weaponPos[position] == weapon )
{
return;
}
self detachAllWeaponModels();
if ( curPosition != "none" )
{
self detachWeapon( weapon );
}
if ( position == "none" )
{
self updateAttachedWeaponModels();
call_overloaded_func( "animscripts\init", "SetWeaponDist" );
return;
}
if ( self.a.weaponPos[position] != "none" )
{
self detachWeapon( self.a.weaponPos[position] );
}
if ( position == "left" || position == "right" )
{
self attachWeapon( weapon, position );
self.weapon = weapon;
self animscripts\anims::clearAnimCache();
self.aimThresholdYaw = 10;
self.aimThresholdPitch = 20;
if( weaponIsGasWeapon( self.weapon ) )
{
self.aimThresholdYaw = 25;
self.aimThresholdPitch = 25;
}
}
else
{
self attachWeapon( weapon, position );
}
self updateAttachedWeaponModels();
call_overloaded_func( "animscripts\init", "SetWeaponDist" );
assert( self.a.weaponPos["left"] == "none" || self.a.weaponPos["right"] == "none" );
}
detachWeapon( weapon )
{
self.a.weaponPos[self.weaponInfo[weapon].position] = "none";
self.weaponInfo[weapon].position = "none";
}
attachWeapon( weapon, position )
{
self.weaponInfo[weapon].position = position;
self.a.weaponPos[position] = weapon;
}
detachAllWeaponModels()
{
if( isdefined(self.weapon_positions) )
{
for ( index = 0; index < self.weapon_positions.size; index++ )
{
weapon = self.a.weaponPos[self.weapon_positions[index]];
if ( weapon == "none" )
{
continue;
}
self detach( getWeaponModel( weapon ), getTagForPos( self.weapon_positions[index] ) );
}
}
}
updateAttachedWeaponModels()
{
if( isdefined(self.weapon_positions) )
{
for ( index = 0; index < self.weapon_positions.size; index++ )
{
weapon = self.a.weaponPos[self.weapon_positions[index]];
if ( weapon == "none" )
{
continue;
}
self attach( getWeaponModel( weapon ), getTagForPos( self.weapon_positions[index] ) );
if ( self.weaponInfo[weapon].useClip && !self.weaponInfo[weapon].hasClip )
{
self hidepart( "tag_clip" );
}
}
}
}
getTagForPos( position )
{
switch ( position )
{
case "chest":
return "tag_weapon_chest";
case "back":
return "tag_stowed_back";
case "left":
return "tag_weapon_left";
case "right":
return "tag_weapon_right";
case "hand":
return "tag_inhand";
default:
assertMsg( "unknown weapon placement position: " + position );
break;
}
}
DropAIWeapon()
{
if (is_true(self.a.dropping_weapons))
{
return;
}
if( self.weapon == "none" || self.weapon == "")
{
return;
}
if (is_true(self.script_nodropsecondaryweapon) && (self.weapon == self.initial_secondaryweapon))
{
PrintLn("Not dropping secondary weapon '" + self.weapon + "'");
return;
}
else if (is_true(self.script_nodropsidearm) && (self.weapon == self.sidearm))
{
PrintLn("Not dropping sidearm '" + self.weapon + "'");
return;
}
self swapDropWeapon();
current_weapon = self.weapon;
position = self.weaponInfo[ current_weapon ].position;
if( IsDefined( current_weapon ) && current_weapon != "none" )
{
animscripts\shared::placeWeaponOn( current_weapon, "none" );
if( current_weapon == self.primaryweapon )
{
self.primaryweapon = "none";
}
else if( current_weapon == self.secondaryweapon )
{
self.secondaryweapon = "none";
}
}
if( self.dropWeapon )
{
dropWeaponName = player_weapon_drop(self.weapon);
velocity = self GetAiVelocity();
speed = Length( velocity ) * 0.5;
droppedWeapon = self DropWeapon( dropWeaponName, position, speed );
}
self.weapon = "none";
}
DropAllAIWeapons()
{
if (is_true(self.a.dropping_weapons))
{
return;
}
if( !self.dropweapon )
{
if( self.weapon != "none" )
{
animscripts\shared::placeWeaponOn( self.weapon, "none" );
self.weapon = "none";
}
return;
}
self.a.dropping_weapons = true;
self swapDropWeapon();
self detachAllWeaponModels();
if( isdefined(self.weapon_positions) )
{
for ( index = 0; index < self.weapon_positions.size; index++ )
{
weapon = self.a.weaponPos[ self.weapon_positions[ index ] ];
if ( weapon != "none" )
{
self.weaponInfo[ weapon ].position = "none";
self.a.weaponPos[ self.weapon_positions[ index ] ] = "none";
if (is_true(self.script_nodropsecondaryweapon) && (weapon == self.initial_secondaryweapon))
{
PrintLn("Not dropping secondary weapon '" + weapon + "'");
}
else if (is_true(self.script_nodropsidearm) && (weapon == self.sidearm))
{
PrintLn("Not dropping sidearm '" + weapon + "'");
}
else
{
weapon = player_weapon_drop(weapon);
velocity = self GetAiVelocity();
speed = Length( velocity ) * 0.5;
droppedWeapon = self DropWeapon( weapon, self.weapon_positions[ index ], speed );
}
}
}
}
self.weapon = "none";
self.a.dropping_weapons = undefined;
}
swapDropWeapon()
{
if (has_script_drop_weapon())
{
found_weapon = false;
for ( i = 0; i < self.weapon_positions.size; i++ )
{
weapon = self.a.weaponPos[ self.weapon_positions[ i ] ];
weapon_toks = StrTok(weapon, "_");
drop_weapon_toks = StrTok(self.script_dropweapon, "_");
if ( weapon_toks[0] == drop_weapon_toks[0] )
{
PrintLn("Swapping out weapon '" + weapon + "' for script_dropweapon '" + self.script_dropweapon + "'");
self placeWeaponOn(weapon, "none");
if (self.weapon == weapon)
{
self.weapon = self.script_dropweapon;
}
self placeWeaponOn(self.script_dropweapon, self.weapon_positions[i]);
found_weapon = true;
break;
}
}
if (!found_weapon)
{
self swapDropWeaponPrimary();
}
self.script_dropweapon = undefined;
}
}
swapDropWeaponPrimary()
{
if (has_script_drop_weapon())
{
position = self.weaponInfo[ self.primaryweapon ].position;
if (position != "none")
{
PrintLn("Swapping out weapon '" + self.primaryweapon + "' for script_dropweapon '" + self.script_dropweapon + "'");
self placeWeaponOn(self.primaryweapon, "none");
self placeWeaponOn(self.script_dropweapon, position);
}
}
}
addPhysWeapon()
{
self thread deleteAtLimit();
}
has_script_drop_weapon()
{
if (IsDefined(self.script_dropweapon) && IsString(self.script_dropweapon) && (self.script_dropweapon != ""))
{
return true;
}
return false;
}
player_weapon_drop(weapon_name)
{
if (IsSubStr( ToLower( weapon_name ), "rpg" ))
{
return "rpg_player_sp";
}
else if (IsSubStr( ToLower( weapon_name ), "panzerschreck" ))
{
return "panzerschreck_player_sp";
}
return weapon_name;
}
deleteAtLimit()
{
wait 30.0;
self delete();
}
HandleDogSoundNoteTracks( note )
{
if ( note == "sound_dogstep_run_default" )
{
self PlaySound( "fly_dog_step_run_default" );
return true;
}
prefix = getsubstr( note, 0, 5 );
if ( prefix != "sound" )
{
return false;
}
alias = "aml" + getsubstr( note, 5 );
if ( IsAlive( self ) )
{
self thread play_sound_on_tag_endon_death( alias, "tag_eye" );
}
else
{
self thread play_sound_in_space( alias, self gettagorigin( "tag_eye" ) );
}
return true;
}
registerNoteTracks()
{
anim.notetracks["anim_pose = \"stand\""] = ::noteTrackPoseStand;
anim.notetracks["anim_pose = \"crouch\""] = ::noteTrackPoseCrouch;
anim.notetracks["anim_pose = \"prone\""] = ::noteTrackPoseProne;
anim.notetracks["anim_pose = \"crawl\""] = ::noteTrackPoseCrawl;
anim.notetracks["anim_pose = \"back\""] = ::noteTrackPoseBack;
anim.notetracks["anim_movement = \"stop\""] = ::noteTrackMovementStop;
anim.notetracks["anim_movement = \"walk\""] = ::noteTrackMovementWalk;
anim.notetracks["anim_movement = \"run\""] = ::noteTrackMovementRun;
anim.notetracks["anim_aiming = 1"] = ::noteTrackAlertnessAiming;
anim.notetracks["anim_aiming = 0"] = ::noteTrackAlertnessAlert;
anim.notetracks["anim_alertness = causal"] = ::noteTrackAlertnessCasual;
anim.notetracks["anim_alertness = alert"] = ::noteTrackAlertnessAlert;
anim.notetracks["anim_alertness = aiming"] = ::noteTrackAlertnessAiming;
anim.notetracks["gunhand = (gunhand)_left"] = ::noteTrackGunhand;
anim.notetracks["anim_gunhand = \"left\""] = ::noteTrackGunhand;
anim.notetracks["anim_gunhand = \"leftright\""] = ::noteTrackGunhand;
anim.notetracks["gunhand = (gunhand)_right"] = ::noteTrackGunhand;
anim.notetracks["anim_gunhand = \"right\""] = ::noteTrackGunhand;
anim.notetracks["anim_gunhand = \"none\""] = ::noteTrackGunhand;
anim.notetracks["gun drop"] = ::noteTrackGunDrop;
anim.notetracks["dropgun"] = ::noteTrackGunDrop;
anim.notetracks["gun_2_chest"] = ::noteTrackGunToChest;
anim.notetracks["gun_2_back"] = ::noteTrackGunToBack;
anim.notetracks["chest_2_back"] = ::noteTrackChestToBack;
anim.notetracks["pistol_pickup"] = ::noteTrackPistolPickup;
anim.notetracks["pistol_putaway"] = ::noteTrackPistolPutaway;
anim.notetracks["drop clip"] = ::noteTrackDropClip;
anim.notetracks["refill clip"] = ::noteTrackRefillClip;
anim.notetracks["reload done"] = ::noteTrackRefillClip;
anim.notetracks["load_shell"] = ::noteTrackLoadShell;
anim.notetracks["pistol_rechamber"] = ::noteTrackPistolRechamber;
anim.notetracks["weapon_switch"] = ::noteTrackWeaponSwitch;
anim.notetracks["gravity on"] = ::noteTrackGravity;
anim.notetracks["gravity off"] = ::noteTrackGravity;
anim.notetracks["bodyfall large"] = ::noteTrackBodyFall;
anim.notetracks["bodyfall small"] = ::noteTrackBodyFall;
anim.notetracks["footstep"] = ::noteTrackFootStep;
anim.notetracks["step"] = ::noteTrackFootStep;
anim.notetracks["footstep_right_large"] = ::noteTrackFootStep;
anim.notetracks["footstep_right_small"] = ::noteTrackFootStep;
anim.notetracks["footstep_left_large"] = ::noteTrackFootStep;
anim.notetracks["footstep_left_small"] = ::noteTrackFootStep;
anim.notetracks["footscrape"] = ::noteTrackFootScrape;
anim.notetracks["land"] = ::noteTrackLand;
anim.notetracks["start_ragdoll"] = ::noteTrackStartRagdoll;
anim.notetracks["fire"] = ::noteTrackFire;
anim.notetracks["fire_spray"] = ::noteTrackFireSpray;
anim.notetracks["fire spray"] = ::noteTrackFireSpray;
anim.notetracks["lookat = \"player\""] = ::noteTrackLookatPlayer;
anim.notetracks["headlookat = \"player\""] =::noteTrackHeadLookatPlayer;
anim.notetracks["lookat = \"\""] = ::noteTrackClearLookAt;
}
noteTrackLookAtPlayer(note, flagName)
{
if(!IsSentient(self))
{
return;
}
relax_ik_headtracking_limits();
self.lookat_set_in_anim = true;
self LookAtEntity(get_players()[0]);
}
noteTrackHeadLookAtPlayer(note, flagName)
{
if(!IsSentient(self))
{
return;
}
relax_ik_headtracking_limits();
SetSavedDvar("ik_dvar_lookatentity_notorso", true);
self.lookat_set_in_anim = true;
self LookAtEntity(get_players()[0]);
}
noteTrackClearLookAt(note, flagName)
{
if(!IsSentient(self))
{
return;
}
restore_ik_headtracking_limits();
self.lookat_set_in_anim = false;
SetSavedDvar("ik_dvar_lookatentity_notorso", false);
self LookAtEntity();
}
noteTrackFire( note, flagName )
{
if (!IsSentient(self))
{
return;
}
if ( IsDefined( anim.fire_notetrack_functions[ self.a.script ] ) )
{
thread [[ anim.fire_notetrack_functions[ self.a.script ] ]]();
}
else
{
thread [[ animscripts\shared::shootNotetrack ]]();
}
}
noteTrackStopAnim( note, flagName )
{
}
noteTrackStartRagdoll( note, flagName )
{
if( IsDefined( self.noragdoll ) )
{
return;
}
self do_ragdoll_death();
}
noteTrackMovementStop( note, flagName )
{
if( IsSentient( self ) )
{
self.a.movement = "stop";
}
}
noteTrackMovementWalk( note, flagName )
{
if( IsSentient( self ) )
{
self.a.movement = "walk";
}
}
noteTrackMovementRun( note, flagName )
{
if( IsSentient( self ) )
{
self.a.movement = "run";
}
}
noteTrackAlertnessAiming( note, flagName )
{
if( IsSentient( self ) )
{
self.a.alertness = "aiming";
}
}
noteTrackAlertnessCasual( note, flagName )
{
if( IsSentient( self ) )
{
self.a.alertness = "casual";
}
}
noteTrackAlertnessAlert( note, flagName )
{
if( IsSentient( self ) )
{
self.a.alertness = "alert";
}
}
noteTrackPoseStand( note, flagName )
{
if( IsSentient( self ) )
{
if (self.a.pose == "prone")
{
self OrientMode ("face default");
self ExitProneWrapper(1.0);
}
self.a.pose = "stand";
self notify ("entered_pose" + "stand");
}
}
noteTrackPoseCrouch( note, flagName )
{
if( IsSentient( self ) )
{
if (self.a.pose == "prone")
{
self OrientMode ("face default");
self ExitProneWrapper(1.0);
}
self.a.pose = "crouch";
self notify ("entered_pose" + "crouch");
if (self.a.crouchPain)
{
self.a.crouchPain = false;
self.health = 150;
}
}
}
noteTrackPoseProne( note, flagName )
{
if( IsSentient( self ) )
{
self setProneAnimNodes( -45, 45, %prone_legs_down, %exposed_aiming, %prone_legs_up );
self EnterProneWrapper(1.0);
self.a.pose = "prone";
self notify ("entered_pose" + "prone");
}
}
noteTrackPoseCrawl( note, flagName )
{
if( IsSentient( self ) )
{
self setProneAnimNodes( -45, 45, %prone_legs_down, %exposed_aiming, %prone_legs_up );
self EnterProneWrapper(1.0);
self.a.pose = "prone";
self notify ("entered_pose" + "prone");
}
}
noteTrackPoseBack( note, flagName )
{
if (self.a.pose == "prone")
{
self ExitProneWrapper(1.0);
}
self.a.pose = "back";
self notify ("entered_pose" + "back");
self.a.movement = "stop";
}
noteTrackGunHand( note, flagName )
{
if ( isSubStr( note, "leftright" ) )
{
animscripts\shared::placeWeaponOn( self.weapon, "left" );
self thread placeWeaponOnRightOnInterrupt();
}
else if ( isSubStr( note, "left" ) )
{
animscripts\shared::placeWeaponOn( self.weapon, "left" );
self notify( "placed_weapon_on_left" );
}
else if ( isSubStr( note, "right" ) )
{
animscripts\shared::placeWeaponOn( self.weapon, "right" );
self notify( "placed_weapon_on_right" );
}
else if ( isSubStr( note, "none" ) )
{
animscripts\shared::placeWeaponOn( self.weapon, "none" );
}
}
placeWeaponOnRightOnInterrupt( )
{
self endon( "death" );
self endon( "placed_weapon_on_right" );
self waittill( "killanimscript" );
if ( AIHasWeapon( self.weapon ) )
{
animscripts\shared::placeWeaponOn( self.weapon, "right" );
}
}
noteTrackGunDrop( note, flagName )
{
self.lastWeapon = self.weapon;
primaryweapon = self.primaryweapon;
secondaryweapon = self.secondaryweapon;
pistolOnlyAI = AIHasOnlyPistol();
self animscripts\shared::DropAIWeapon();
if ( self.lastWeapon == primaryweapon )
{
self.weapon = self.secondaryweapon;
}
else if ( self.lastWeapon == secondaryweapon )
{
self.weapon = self.primaryweapon;
}
self animscripts\anims::clearAnimCache();
}
noteTrackGunToChest( note, flagName )
{
animscripts\shared::placeWeaponOn( self.weapon, "chest" );
}
noteTrackGunToBack( note, flagName )
{
animscripts\shared::placeWeaponOn( self.weapon, "back" );
self.weapon = self getPreferredWeapon();
self.bulletsInClip = weaponClipSize( self.weapon );
self animscripts\anims::clearAnimCache();
}
noteTrackChestToBack( note, flagName )
{
assert( hasSecondaryWeapon() );
animscripts\shared::placeWeaponOn( getSecondaryWeapon(), "back" );
}
noteTrackPistolPickup( note, flagName )
{
if( AIHasSidearm() )
{
animscripts\shared::placeWeaponOn( self.sidearm, "right" );
self.bulletsInClip = weaponClipSize( self.weapon );
self notify ( "weapon_switch_done" );
}
}
noteTrackPistolPutaway( note, flagName )
{
animscripts\shared::placeWeaponOn( self.weapon, "none" );
self.weapon = self getPreferredWeapon();
self.bulletsInClip = weaponClipSize( self.weapon );
self animscripts\anims::clearAnimCache();
}
noteTrackWeaponSwitch( note, flagName )
{
assertex( hasSecondaryWeapon(), "no secondary weapon available! check the aitype for this actor. " );
if( self.weapon == self.primaryweapon )
{
if( self.weapon != "none" )
{
self animscripts\shared::placeWeaponOn( self.weapon, "back" );
}
self animscripts\shared::placeWeaponOn( self.secondaryweapon, "right" );
}
else
{
if( self.weapon != "none" )
{
self animscripts\shared::placeWeaponOn( self.weapon, "back" );
}
self animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
}
clipSize = weaponClipSize( self.weapon );
if (NeedToReload( 0.5 ))
{
if(clipSize > 1)
{
self.bulletsInClip = Int(clipSize * 0.5);
}
else
{
self.bulletsInClip = clipSize;
}
}
else if( self.bulletsInClip > clipSize )
{
self.bulletsInClip = clipSize;
}
self notify( "complete_weapon_switch" );
noteTrackWeaponSwitchGlint( note, flagName );
self.lastWeapon = self.weapon;
}
noteTrackWeaponSwitchGlint( note, flagName )
{
if (IsDefined(self.weapon))
{
}
}
noteTrackDropClip( note, flagName )
{
self thread handleDropClip( flagName );
}
noteTrackRefillClip( note, flagName )
{
if ( weaponClass( self.weapon ) == "rocketlauncher" )
{
self showRocket();
}
self animscripts\weaponList::RefillClip();
}
noteTrackLoadShell( note, flagName )
{
}
noteTrackPistolRechamber( note, flagName )
{
}
noteTrackGravity( note, flagName )
{
if ( isSubStr( note, "on" ) )
{
self AnimMode( "gravity" );
}
else if ( isSubStr( note, "off" ) )
{
self AnimMode( "nogravity" );
}
}
noteTrackBodyFall( note, flagName )
{
if ( IsDefined( self.groundType ) )
{
groundType = self.groundType;
}
else
{
groundType = "dirt";
}
if ( isSubStr( note, "large" ) )
{
self PlaySound ("fly_bodyfall_large_" + groundType);
}
else if ( isSubStr( note, "small" ) )
{
self PlaySound ("fly_bodyfall_small_" + groundType);
}
}
noteTrackFootStep( note, flagName )
{
if ( isSubStr( note, "left" ) )
{
playFootStep( "J_Ball_LE" );
}
else
{
playFootStep( "J_BALL_RI" );
}
if(!level.clientScripts)
{
self PlaySound( "fly_gear_run" );
}
}
noteTrackFootScrape( note, flagName )
{
if ( IsDefined( self.groundType ) )
{
groundType = self.groundType;
}
else
{
groundType = "dirt";
}
self PlaySound ("fly_step_scrape_" + groundType );
}
noteTrackLand( note, flagName )
{
if ( IsDefined( self.groundType ) )
{
groundType = self.groundType;
}
else
{
groundType = "dirt";
}
if(IsPlayer ( self ))
{
self PlaySound ("fly_land_plr_" + groundType );
}
else
{
self PlaySound ("fly_land_npc_" + groundType);
}
}
HandleNoteTrack( note, flagName, customFunction, var1 )
{
if ( isAI( self ) && self.isdog )
{
if ( HandleDogSoundNoteTracks( note ) )
{
return;
}
}
notetrackFunc = anim.notetracks[note];
if ( IsDefined( notetrackFunc ) )
{
return [[notetrackFunc]]( note, flagName );
}
switch ( note )
{
case "end":
case "finish":
case "undefined":
if ( isAI(self) && self.a.pose=="back" )
{
}
return note;
case "swish small":
self thread play_sound_in_space ("wpn_melee_swing_large", self gettagorigin ("TAG_WEAPON_RIGHT"));
break;
case "swish large":
self thread play_sound_in_space ("wpn_melee_swing_large", self gettagorigin ("TAG_WEAPON_RIGHT"));
break;
case "rechamber":
if ( self usingShotgun() )
break;
case "no death":
self.a.nodeath = true;
break;
case "no pain":
self disable_pain();
break;
case "allow pain":
self enable_pain();
break;
case "anim_melee = right":
case "anim_melee = \"right\"":
self.a.meleeState = "right";
break;
case "anim_melee = left":
case "anim_melee = \"left\"":
self.a.meleeState = "left";
break;
case "weapon_retrieve":
break;
case "swap taghelmet to tagleft":
if ( IsDefined ( self.hatModel ) )
{
if (IsDefined(self.helmetSideModel))
{
self detach(self.helmetSideModel, "TAG_HELMETSIDE");
self.helmetSideModel = undefined;
}
self detach ( self.hatModel, "");
self attach ( self.hatModel, "TAG_WEAPON_LEFT");
self.hatModel = undefined;
}
break;
case "stop anim":
anim_stopanimscripted();
return note;
default:
if (IsDefined(customFunction))
{
if (!IsDefined(var1))
{
return [[customFunction]] (note);
}
else
{
return [[customFunction]] (note, var1);
}
}
break;
}
}
DoNoteTracks( flagName, customFunction, debugIdentifier, var1 )
{
for (;;)
{
self waittill (flagName, note);
if ( !IsDefined( note ) )
{
note = "undefined";
}
val = self HandleNoteTrack( note, flagName, customFunction, var1 );
if ( IsDefined( val ) )
{
return val;
}
}
}
DoNoteTracksIntercept( flagName, interceptFunction, debugIdentifier )
{
assert( IsDefined( interceptFunction ) );
for (;;)
{
self waittill ( flagName, note );
if ( !IsDefined( note ) )
{
note = "undefined";
}
intercepted = [[interceptFunction]]( note );
if ( IsDefined( intercepted ) && intercepted )
{
continue;
}
val = self HandleNoteTrack( note, flagName );
if ( IsDefined( val ) )
{
return val;
}
}
}
DoNoteTracksPostCallback( flagName, postFunction )
{
assert( IsDefined( postFunction ) );
for (;;)
{
self waittill ( flagName, note );
if ( !IsDefined( note ) )
{
note = "undefined";
}
val = self HandleNoteTrack( note, flagName );
[[postFunction]]( note );
if ( IsDefined( val ) )
{
return val;
}
}
}
DoNoteTracksForever(flagName, killString, customFunction, debugIdentifier)
{
DoNoteTracksForeverProc( ::DoNoteTracks, flagName, killString, customFunction, debugIdentifier);
}
DoNoteTracksForeverIntercept(flagName, killString, interceptFunction, debugIdentifier)
{
DoNoteTracksForeverProc( ::DoNoteTracksIntercept, flagName, killString, interceptFunction, debugIdentifier );
}
DoNoteTracksForeverProc( notetracksFunc, flagName, killString, customFunction, debugIdentifier )
{
if (IsDefined (killString))
{
self endon (killString);
}
self endon ("killanimscript");
if (!IsDefined(debugIdentifier))
{
debugIdentifier = "undefined";
}
for (;;)
{
time = GetTime();
returnedNote = [[notetracksFunc]](flagName, customFunction, debugIdentifier);
timetaken = GetTime() - time;
if ( timetaken < 0.05)
{
time = GetTime();
returnedNote = [[notetracksFunc]](flagName, customFunction, debugIdentifier);
timetaken = GetTime() - time;
if ( timetaken < 0.05)
{
println (GetTime()+" "+debugIdentifier+" animscripts\shared::DoNoteTracksForever is trying to cause an infinite loop on anim "+flagName+", returned "+returnedNote+".");
wait ( 0.05 - timetaken );
}
}
}
}
DoNoteTracksForTime(time, flagName, customFunction, debugIdentifier)
{
ent = SpawnStruct();
ent thread doNoteTracksForTimeEndNotify(time);
DoNoteTracksForTimeProc( ::DoNoteTracksForever, time, flagName, customFunction, debugIdentifier, ent);
}
DoNoteTracksForTimeIntercept( time, flagName, interceptFunction, debugIdentifier)
{
ent = SpawnStruct();
ent thread doNoteTracksForTimeEndNotify(time);
DoNoteTracksForTimeProc( ::DoNoteTracksForeverIntercept, time, flagName, interceptFunction, debugIdentifier, ent);
}
DoNoteTracksForTimeProc( doNoteTracksForeverFunc, time, flagName, customFunction, debugIdentifier, ent)
{
ent endon ("stop_notetracks");
[[doNoteTracksForeverFunc]](flagName, undefined, customFunction, debugIdentifier);
}
doNoteTracksForTimeEndNotify(time)
{
wait (time);
self notify ("stop_notetracks");
}
playFootStep(foot)
{
if(!level.clientScripts)
{
if (! isAI(self) )
{
self PlaySound ("fly_step_run_dirt");
return;
}
}
groundType = undefined;
if (!IsDefined(self.groundtype))
{
if (!IsDefined(self.lastGroundtype))
{
if(!level.clientScripts)
{
self PlaySound ("fly_step_run_dirt");
}
return;
}
groundtype = self.lastGroundtype;
}
else
{
groundtype = self.groundtype;
self.lastGroundtype = self.groundType;
}
if(!level.clientScripts)
{
self PlaySound ("fly_step_run_" + groundType);
}
[[anim.optionalStepEffectFunction]](foot, groundType);
}
playFootStepEffect(foot, groundType)
{
if(level.clientScripts)
{
return;
}
for (i=0;i<anim.optionalStepEffects.size;i++)
{
if( IsDefined( self.fire_footsteps ) && self.fire_footsteps )
{
groundType = "fire";
}
if (groundType != anim.optionalStepEffects[i])
{
continue;
}
org = self gettagorigin(foot);
playfx(level._effect["step_" + anim.optionalStepEffects[i]], org, org + (0,0,100));
return;
}
}
shootNotetrack()
{
waittillframeend;
now = GetTime();
if ( now > self.a.lastShootTime )
{
self.a.lastShootTime = now;
self shootEnemyWrapper();
self decrementBulletsInClip();
if ( weaponClass( self.weapon ) == "rocketlauncher" )
{
self.a.rockets--;
}
}
}
fire_straight()
{
if( self.a.weaponPos[ "right" ] == "none" && self.a.weaponPos[ "left" ] == "none" )
{
return;
}
if ( IsDefined( self.dontShootStraight ) )
{
shootNotetrack();
return;
}
weaporig = self gettagorigin( "tag_weapon" );
dir = AnglesToForward( self GetTagAngles( "tag_weapon" ) );
pos = weaporig + vector_scale( dir, 1000 );
self.a.lastShootTime = GetTime();
self shoot( 1, pos );
self decrementBulletsInClip();
}
noteTrackFireSpray( note, flagName )
{
if ( self.a.weaponPos["right"] == "none" )
{
return;
}
weaporig = self gettagorigin("tag_weapon");
dir = AnglesToForward( self GetTagAngles( "tag_weapon" ) );
hitenemy = false;
if ( IsSentient(self.enemy) && IsAlive(self.enemy) && self canShoot( self.enemy GetShootAtPos() ) )
{
enemydir = VectorNormalize(self.enemy geteye() - weaporig);
if ( vectordot(dir, enemydir) > cos(10) )
{
hitenemy = true;
}
}
if ( hitenemy )
{
self shootEnemyWrapper();
}
else
{
dir += ((RandomFloat(2)-1) * .1, (RandomFloat(2)-1) * .1, (RandomFloat(2)-1) * .1);
pos = weaporig + vector_scale(dir, 1000);
self shootPosWrapper( pos );
}
self decrementBulletsInClip();
}
getPredictedAimYawToShootEntOrPos(time)
{
if ( !IsDefined( self.shootEnt ) )
{
if ( !IsDefined( self.shootPos ) )
{
return 0;
}
return getAimYawToPoint( self.shootPos );
}
predictedPos = self.shootEnt.origin + vector_scale( self.shootEntVelocity, time );
return getAimYawToPoint( predictedPos );
}
getAimYawToShootEntOrPos()
{
if ( !IsDefined( self.shootEnt ) )
{
if ( !IsDefined( self.shootPos ) )
{
return 0;
}
return getAimYawToPoint( self.shootPos );
}
return getAimYawToPoint( self.shootEnt GetShootAtPos(self) );
}
getAimPitchToShootEntOrPos()
{
pitch = getPitchToShootEntOrPos();
if ( self.a.script == "cover_crouch" && IsDefined( self.a.coverMode ) && self.a.coverMode == "lean" )
{
pitch -= anim.coverCrouchLeanPitch;
}
return pitch;
}
getPitchToShootEntOrPos()
{
if ( !IsDefined( self.shootEnt ) )
{
if ( !IsDefined( self.shootPos ) )
{
return 0;
}
return animscripts\combat_utility::getPitchToSpot( self.shootPos );
}
return animscripts\combat_utility::getPitchToSpot( self.shootEnt GetShootAtPos(self) );
}
getAimYawToPoint(point)
{
yaw = GetYawToSpot(point);
dist = distance(self.origin,point);
if(dist > 3)
{
angleFudge = asin(-3/dist);
yaw += angleFudge;
}
yaw = AngleClamp180( yaw );
return yaw;
}
trackShootEntOrPos()
{
self animscripts\shared::setAimingAnims( %aim_2, %aim_4, %aim_6, %aim_8 );
self animscripts\shared::trackLoopStart();
}
trackLoopStart()
{
self notify("trackLoopStart");
self.pauseTrackLoop = false;
}
trackLoopPause()
{
self endon("death");
while(1)
{
self waittill_any( "killanimscript", "stop tracking", "melee" );
self.pauseTrackLoop = true;
}
}
trackLoopPacer()
{
self endon("death");
wait(0.05);
self notify("trackLoopStart");
}
scriptNeedsTagAim()
{
if( IsDefined( self.a.script ) )
{
if( self.a.script == "move" || self.a.script == "cover_right" || self.a.script == "cover_left" || self.a.script == "cover_pillar" )
{
return true;
}
}
return false;
}
trackLoopGetShootFromPos()
{
origin = undefined;
if( scriptNeedsTagAim() )
{
origin = self getTagOrigin( "tag_aim" );
}
if( !IsDefined(origin) )
{
eyeHeight = self geteyeapprox()[2];
if( self.a.pose == "crouch" )
{
eyeHeight = self.origin[2] + (eyeHeight - self.origin[2]) * 0.5;
}
origin = (self.origin[0], self.origin[1], eyeHeight);
}
return origin;
}
trackLoopGetShootFromAngles()
{
angles = undefined;
if( scriptNeedsTagAim() )
{
angles = self getTagAngles( "tag_aim" );
}
if( !IsDefined(angles) )
{
angles = self.angles;
}
return angles;
}
trackLoop()
{
self endon("death");
self.aimAngleOffset = 0;
self.pitchAngleOffset = 0;
self waittill("trackLoopStart");
players = GetPlayers();
prevYawDelta = 0;
prevPitchDelta = 0;
prevAim2 = self.a.aim_2;
maxYawDeltaChange = 5;
maxPitchDeltaChange = 5;
yawDelta = 0;
yawAdd = 0;
pitchDelta = 0;
pitchAdd = 0;
if ( self.isdog )
{
doMaxAngleCheck = false;
self.shootEnt = self.enemy;
}
else
{
doMaxAngleCheck = true;
}
firstFrame = true;
self.pauseTrackLoop = false;
self thread trackLoopPause();
shootFromAngles = self trackLoopGetShootFromAngles();
prevshootFromYawAngle = shootFromAngles[1] + self.aimAngleOffset;
prevshootFromPitchAngle = shootFromAngles[0] + self.pitchAngleOffset;
for(;;)
{
rightAimLimit = self.rightAimLimit;
leftAimLimit = self.leftAimLimit;
upAimLimit = self.upAimLimit;
downAimLimit = self.downAimLimit;
if ( prevYawDelta > rightAimLimit )
{
prevYawDelta = rightAimLimit;
}
else if ( prevYawDelta < leftAimLimit )
{
prevYawDelta = leftAimLimit;
}
if ( prevPitchDelta > upAimLimit )
{
prevPitchDelta = upAimLimit;
}
else if ( prevPitchDelta < downAimLimit )
{
prevPitchDelta = downAimLimit;
}
aimingAnimsChanged = false;
aimBlendTime = .05;
if( prevAim2 != self.a.aim_2 )
{
aimingAnimsChanged = true;
aimBlendTime = 0;
prevAim2 = self.a.aim_2;
}
incrAnimAimWeight();
shootFromPos = self trackLoopGetShootFromPos();
shootPos = self.shootPos;
if ( IsDefined( self.shootEnt ) )
{
shootPos = self.shootEnt GetShootAtPos(self, self, self);
}
if ( !IsDefined( shootPos ) && self call_overloaded_func( "animscripts\cqb", "shouldCQB" ) )
{
selfForward = AnglesToForward( self.angles );
if ( IsDefined( self.cqb_target ) )
{
shootPos = self.cqb_target GetShootAtPos(self);
dir = shootPos - shootFromPos;
vdot = vectorDot( dir, selfForward );
if ( ( vdot < 0.0 ) || ( vdot * vdot < 0.413449 * lengthsquared( dir ) ) )
{
shootPos = undefined;
}
}
if ( !IsDefined( shootPos ) && IsDefined( self.cqb_point_of_interest ) )
{
shootPos = self.cqb_point_of_interest;
dir = shootPos - shootFromPos;
vdot = vectorDot( dir, selfForward );
if ( ( vdot < 0.0 ) || ( vdot * vdot < 0.413449 * lengthsquared( dir ) ) )
{
shootPos = undefined;
}
}
}
shootFromAngles = self trackLoopGetShootFromAngles();
shootFromYawAngle = shootFromAngles[1] + self.aimAngleOffset;
shootFromPitchAngle = shootFromAngles[0] + self.pitchAngleOffset;
shootFromYawDelta = AngleClamp180(shootFromYawAngle - prevshootFromYawAngle);
shootFromPitchDelta = AngleClamp180(shootFromPitchAngle - prevshootFromPitchAngle);
maxAngleDelta = 10;
if( abs(shootFromYawDelta) > maxAngleDelta )
{
shootFromYawAngle = prevshootFromYawAngle + maxAngleDelta * sign(shootFromYawDelta);
}
if( abs(shootFromPitchDelta) > maxAngleDelta )
{
shootFromPitchAngle = prevshootFromPitchAngle + maxAngleDelta * sign(shootFromPitchDelta);
}
shootFromAngles = ( shootFromPitchAngle, shootFromYawAngle, shootFromAngles[2] );
if ( !IsDefined( shootPos ) )
{
assert( !IsDefined( self.shootEnt ) );
if ( IsDefined( self.node ) && self.node.type == "Guard" && DistanceSquared(self.origin, self.node.origin) < 16 )
{
yawDelta = AngleClamp180( shootFromYawAngle - self.node.angles[1] );
pitchDelta = 0;
}
else
{
likelyEnemyDir = self getAnglesToLikelyEnemyPath();
if ( IsDefined( likelyEnemyDir ) )
{
yawDelta = AngleClamp180( shootFromYawAngle - likelyEnemyDir[1] );
pitchDelta = AngleClamp180( 360 - likelyEnemyDir[0] );
}
else
{
yawDelta = 0;
pitchDelta = 0;
}
}
}
else
{
vectorToShootPos = shootPos - shootFromPos;
anglesToShootPos = VectorToAngles( vectorToShootPos );
yawDelta = shootFromYawAngle - anglesToShootPos[1];
yawDelta = AngleClamp180( yawDelta + yawAdd );
pitchDelta = shootFromPitchAngle - anglesToShootPos[0];
pitchDelta = AngleClamp180( pitchDelta + pitchAdd );
}
if ( doMaxAngleCheck && !aimingAnimsChanged && ( abs( yawDelta ) > 60 || abs( pitchDelta ) > 60 ) )
{
yawDelta = 0;
pitchDelta = 0;
}
else
{
if ( yawDelta > rightAimLimit )
{
yawDelta = rightAimLimit;
}
else if ( yawDelta < leftAimLimit )
{
yawDelta = leftAimLimit;
}
if ( pitchDelta > upAimLimit )
{
pitchDelta = upAimLimit;
}
else if ( pitchDelta < downAimLimit )
{
pitchDelta = downAimLimit;
}
}
if ( firstFrame )
{
firstFrame = false;
yawDelta = 0;
pitchDelta = 0;
}
else
{
adjustedMaxYawDeltaChange = maxYawDeltaChange + abs(shootFromYawDelta);
adjustedMaxPitchDeltaChange = maxPitchDeltaChange + abs(shootFromPitchDelta);
yawDeltaChange = yawDelta - prevYawDelta;
if ( abs( yawDeltaChange ) > adjustedMaxYawDeltaChange )
yawDelta = prevYawDelta + adjustedMaxYawDeltaChange * sign( yawDeltaChange );
pitchDeltaChange = pitchDelta - prevPitchDelta;
if ( abs( pitchDeltaChange ) > adjustedMaxPitchDeltaChange )
pitchDelta = prevPitchDelta + adjustedMaxPitchDeltaChange * sign( pitchDeltaChange );
}
prevshootFromYawAngle = shootFromYawAngle;
prevshootFromPitchAngle = shootFromPitchAngle;
prevYawDelta = yawDelta;
prevPitchDelta = pitchDelta;
if ( yawDelta > 0 )
{
assert( yawDelta <= rightAimLimit );
weight = yawDelta / rightAimLimit * self.a.aimweight;
self SetAnimLimited( self.a.aim_4, 0, aimBlendTime );
self SetAnimLimited( self.a.aim_6, weight, aimBlendTime );
}
else if ( yawDelta < 0 )
{
assert( yawDelta >= leftAimLimit );
weight = yawDelta / leftAimLimit * self.a.aimweight;
self SetAnimLimited( self.a.aim_6, 0, aimBlendTime );
self SetAnimLimited( self.a.aim_4, weight, aimBlendTime );
}
if ( pitchDelta > 0 )
{
assert( pitchDelta <= upAimLimit );
weight = pitchDelta / upAimLimit * self.a.aimweight;
self SetAnimLimited( self.a.aim_2, 0, aimBlendTime );
self SetAnimLimited( self.a.aim_8, weight, aimBlendTime );
}
else if ( pitchDelta < 0 )
{
assert( pitchDelta >= downAimLimit );
weight = pitchDelta / downAimLimit * self.a.aimweight;
self SetAnimLimited( self.a.aim_8, 0, aimBlendTime );
self SetAnimLimited( self.a.aim_2, weight, aimBlendTime );
}
if ( players.size == 1 )
{
self thread trackLoopPacer();
self waittill("trackLoopStart");
waittillframeend;
}
else
{
wait( 1 );
}
if( self.pauseTrackLoop )
{
self.aimAngleOffset = 0;
self.pitchAngleOffset = 0;
self waittill("trackLoopStart");
self.pauseTrackLoop = false;
firstFrame = true;
prevYawDelta = 0;
prevPitchDelta = 0;
shootFromAngles = self trackLoopGetShootFromAngles();
prevshootFromYawAngle = shootFromAngles[1] + self.aimAngleOffset;
prevshootFromPitchAngle = shootFromAngles[0] + self.pitchAngleOffset;
}
}
}
setAnimAimWeight(goalweight, goaltime)
{
if ( !IsDefined( goaltime ) || goaltime <= 0 )
{
self.a.aimweight = goalweight;
self.a.aimweight_start = goalweight;
self.a.aimweight_end = goalweight;
self.a.aimweight_transframes = 0;
}
else
{
if ( !isdefined( self.a.aimweight ) )
self.a.aimweight = 0;
self.a.aimweight_start = self.a.aimweight;
self.a.aimweight_end = goalweight;
self.a.aimweight_transframes = int(goaltime * 20);
}
self.a.aimweight_t = 0;
}
incrAnimAimWeight()
{
if ( self.a.aimweight_t < self.a.aimweight_transframes )
{
self.a.aimweight_t++;
t = 1.0 * self.a.aimweight_t / self.a.aimweight_transframes;
self.a.aimweight = self.a.aimweight_start * (1 - t) + self.a.aimweight_end * t;
}
}
decideNumShotsForBurst()
{
numShots = 0;
if ( animscripts\weaponList::usingSemiAutoWeapon() )
{
numShots = anim.semiFireNumShots[ RandomInt( anim.semiFireNumShots.size ) ];
}
else if ( self.fastBurst )
{
numShots = anim.fastBurstFireNumShots[ RandomInt( anim.fastBurstFireNumShots.size ) ];
}
else
{
numShots = anim.burstFireNumShots[ RandomInt( anim.burstFireNumShots.size ) ];
}
if ( numShots <= self.bulletsInClip )
{
return numShots;
}
assertex( self.bulletsInClip >= 0, self.bulletsInClip );
if ( self.bulletsInClip <= 0 )
{
return 1;
}
return self.bulletsInClip;
}
decideNumShotsForFull()
{
numShots = self.bulletsInClip;
if ( weaponClass( self.weapon ) == "mg" )
{
choice = RandomFloat(10);
if ( choice < 3 )
{
numShots = randomIntRange( 2, 6 );
}
else if ( choice < 8 )
{
numShots = randomIntRange( 6, 12 );
}
else
{
numShots = randomIntRange( 12, 20 );
}
}
return numShots;
}
handleDropClip( flagName )
{
self endon ( "killanimscript" );
self endon ( "abort_reload" );
if ( !IsSentient( self ) )
{
return;
}
clipModel = undefined;
if ( self.weaponInfo[self.weapon].useClip )
{
clipModel = getWeaponClipModel( self.weapon );
if ( !IsDefined( level.weaponClipModelsLoaded ) || !IsDefined( anim._effect[ clipModel ] ) )
{
println("^1Warning: Couldn't drop clip model " + clipModel + " because it is not in level.weaponClipModels so it probably wasn't precached.");
println("^1Set dvar scr_generateClipModels to 1 and map_restart, then follow instructions in console.");
clipModel = undefined;
}
}
if ( self.weaponInfo[self.weapon].hasClip )
{
if ( weaponAnims() == "pistol" )
{
}
else
{
}
if ( IsDefined( clipModel ) )
{
self hidepart( "tag_clip" );
assert( IsDefined( anim._effect[clipModel] ) );
playFxOnTag( anim._effect[clipModel], self, "tag_clip" );
self.weaponInfo[self.weapon].hasClip = false;
self thread resetClipOnAbort( clipModel );
}
}
for ( ;; )
{
self waittill( flagName, noteTrack );
switch ( noteTrack )
{
case "attach clip left":
case "attach clip right":
if ( IsDefined( clipModel ) )
{
self attach( clipModel, "tag_inhand" );
self hidepart( "tag_clip" );
self thread resetClipOnAbort( clipModel, "tag_inhand" );
}
self animscripts\weaponList::RefillClip();
break;
case "detach clip right":
case "detach clip left":
if ( IsDefined( clipModel ) )
{
self detach( clipModel, "tag_inhand" );
self showpart( "tag_clip" );
self notify ( "clip_detached" );
self.weaponInfo[self.weapon].hasClip = true;
}
if ( weaponAnims() == "pistol" )
{
}
else
{
}
return;
}
}
}
resetClipOnAbort( clipModel, currentTag )
{
self notify ( "clip_detached" );
self endon ( "clip_detached" );
self waittill_any( "killanimscript", "abort_reload" );
if ( !IsDefined( self ) )
{
return;
}
if ( IsDefined( currentTag ) )
{
self detach( clipModel, currentTag );
}
if ( IsAlive( self ) )
{
self showpart( "tag_clip" );
self.weaponInfo[self.weapon].hasClip = true;
}
else
{
if ( IsDefined( currentTag ) && IsDefined( anim._effect[clipModel] ) )
{
playFxOnTag( anim._effect[clipModel], self, currentTag );
}
}
}
moveToOriginOverTime( origin, time )
{
self endon("killanimscript");
if ( DistanceSquared( self.origin, origin ) > 16*16 && !self mayMoveToPoint( origin ) )
{
return;
}
self.keepClaimedNodeInGoal = true;
offset = self.origin - origin;
frames = int(time * 20);
offsetreduction = vector_scale( offset, 1.0 / frames );
for ( i = 0; i < frames; i++ )
{
offset -= offsetreduction;
self Teleport( origin + offset );
wait .05;
}
self.keepClaimedNodeInGoal = false;
}
returnTrue() { return true; }
playLookAnimation( lookAnim, lookTime, canStopCallback )
{
if ( !IsDefined( canStopCallback ) )
{
canStopCallback = ::returnTrue;
}
for ( i = 0; i < lookTime * 10; i++ )
{
if ( IsAlive( self.enemy ) )
{
if ( self canSeeEnemy() && [[ canStopCallback ]]() )
{
return;
}
}
if ( self isSuppressedWrapper() && [[ canStopCallback ]]() )
{
return;
}
self SetAnimKnobAll( lookAnim, %body, 1, .1 );
wait (0.1);
}
}
getSecondaryWeapon()
{
if( IsDefined(self.weapon) )
{
if( self.weapon == self.primaryweapon && AIHasWeapon(self.secondaryweapon) && weaponClass(self.secondaryweapon) != "pistol" )
{
return self.secondaryweapon;
}
else if( self.weapon == self.secondaryweapon && AIHasWeapon(self.primaryweapon) && weaponClass(self.secondaryweapon) != "pistol" )
{
return self.primaryweapon;
}
}
return undefined;
}
hasSecondaryWeapon()
{
weapon = getSecondaryWeapon();
return( IsDefined(weapon) && (weapon != "none") );
}
shouldThrowDownWeapon()
{
if( !hasSecondaryWeapon() )
{
return false;
}
if( !self.a.allow_weapon_switch )
{
return false;
}
curWeaponClass = weaponAnims();
if( curWeaponClass == "none" )
{
return false;
}
if( IsDefined(self.shootPos) )
{
distSqToShootPos = lengthsquared( self.origin - self.shootPos );
if ( weaponAnims() == "rocketlauncher" && (distSqToShootPos < squared( 512 ) || self.a.rockets < 1 ) )
{
return true;
}
}
return false;
}
throwDownWeapon()
{
self endon ( "killanimscript" );
swapAnim = animArray("throw_down_weapon");
if( !IsDefined(swapAnim) || swapAnim == %void )
{
return;
}
self AnimMode( "angle deltas" );
self SetFlaggedAnimKnobAllRestart( "weapon swap", swapAnim, %body, 1, .1, 1 );
note = "";
while (note!="end")
{
self waittill("weapon swap",note);
if ( note == "dropgun" || note == "gun drop")
{
DropAIWeapon();
}
if ( note == "anim_gunhand = \"right\"" )
{
assertex( hasSecondaryWeapon(), "self.secondaryweapon not defined! check the aitype for this actor. " );
if( AIHasWeapon(self.secondaryweapon) )
{
self animscripts\shared::placeWeaponOn( self.secondaryweapon, "right" );
}
else
{
self animscripts\shared::placeWeaponOn( self.primaryweapon, "right" );
}
}
}
if( self.bulletsInClip > weaponClipSize( self.weapon ) )
{
self.bulletsInClip = weaponClipSize( self.weapon );
}
self maps\_gameskill::didSomethingOtherThanShooting();
}
shouldSwitchWeapons()
{
if (!hasSecondaryWeapon() || !self.a.allow_weapon_switch)
{
return false;
}
if( self.a.atPillarNode )
{
return false;
}
if( IsDefined(self.a.weapon_switch_ASAP) && (self.a.weapon_switch_ASAP) )
{
assertex( hasSecondaryWeapon(), "self.secondaryweapon not defined! check the aitype for this actor. " );
self.a.weapon_switch_ASAP = false;
return true;
}
if( (gettime() - self.a.weapon_switch_time) < 1000 )
{
return false;
}
if(GetDvarInt( #"aiForceSwitchWeapons"))
{
return true;
}
curWeaponClass = weaponAnims();
if( curWeaponClass == "none" )
{
return true;
}
if( shouldSwitchWeaponForSituation() )
{
return true;
}
if ( shouldSwitchWeaponForDistance() )
{
return true;
}
return false;
}
shouldSwitchWeaponForDistance()
{
if( ( weaponAnims() == "rocketlauncher" && isEnemyInExplodableVolume() ) || !IsSentient( self.enemy ) )
{
return false;
}
if ( IsDefined( self.shootPos ) )
{
distSqToShootPos = lengthsquared( self.origin - self.shootPos );
shouldUseWeapon = undefined;
Assert( IsDefined( self.primaryweapon_fightdist_minSq ) );
Assert( IsDefined( self.secondaryweapon_fightdist_minSq ) );
withinPrimaryRange = ( ( self.primaryweapon_fightdist_minSq < distSqToShootPos ) && ( distSqToShootPos < self.primaryweapon_fightdist_maxSq ) );
withinSecondaryRange = ( ( self.secondaryweapon_fightdist_minSq < distSqToShootPos ) && ( distSqToShootPos < self.secondaryweapon_fightdist_maxSq ) );
if( ( withinPrimaryRange && withinSecondaryRange ) || ( !withinPrimaryRange && !withinSecondaryRange ) )
{
if (IsDefined(self.enemy))
{
primaryweapon_accuracy = getweaponaccuracy(self, self.primaryweapon);
secondaryweapon_accuracy = getweaponaccuracy(self, self.secondaryweapon);
if ( primaryweapon_accuracy > secondaryweapon_accuracy )
{
shouldUseWeapon = self.primaryweapon;
}
else
{
shouldUseWeapon = self.secondaryweapon;
}
}
else
{
shouldUseWeapon = self.weapon;
}
}
else
{
if ( withinPrimaryRange )
{
shouldUseWeapon = self.primaryweapon;
}
else if ( withinSecondaryRange )
{
shouldUseWeapon = self.secondaryweapon;
}
}
Assert( IsDefined(shouldUseWeapon) );
if ( self.weapon != shouldUseWeapon )
{
if( self.a.weapon_switch_for_distance_time < 0 )
{
self.a.weapon_switch_for_distance_time = GetTime() + RandomFloatRange(2, 4) * 1000;
}
if( isExposed() && GetTime() < self.a.weapon_switch_for_distance_time )
{
return false;
}
return true;
}
self.a.weapon_switch_for_distance_time = -1;
return false;
}
self.a.weapon_switch_for_distance_time = -1;
return false;
}
isExposed()
{
if( self.a.script == "cover_crouch" || self.a.script == "cover_stand" )
{
if( IsDefined(self.a.coverMode) && self.a.coverMode == "Hide" )
{
return false;
}
}
else if( self.a.script == "cover_left" || self.a.script == "cover_right" || self.a.script == "cover_pillar" )
{
if( !IsDefined(self.cornerAiming) || !self.cornerAiming )
{
return false;
}
}
return true;
}
getWeaponSwitchAnim()
{
animName = "weapon_switch";
if( !isExposed() )
{
animName = "weapon_switch_cover";
if(GetDvarInt( #"aiQuadrantSwitch") == 1)
{
animName = "weapon_switch_quadrants_cover";
}
else if(GetDvarInt( #"aiQuadrantSwitch") == 2)
{
animName = "weapon_putaway_cover";
}
}
else
{
if(GetDvarInt( #"aiQuadrantSwitch") == 1)
{
animName = "weapon_switch_quadrants";
}
else if(GetDvarInt( #"aiQuadrantSwitch") == 2)
{
animName = "weapon_putaway";
}
}
if( IsArray( animArray(animName) ) )
{
return animArrayPickRandom( animName );
}
return animArray(animName);
}
getWeaponPulloutAnim()
{
animName = "weapon_pullout";
if( !isExposed() )
{
animName = "weapon_pullout_cover";
}
assert( animArrayExist(animName) );
if( IsArray( animArray(animName) ) )
{
return animArrayPickRandom( animName );
}
return animArray(animName);
}
switchWeapons()
{
swapAnim = getWeaponSwitchAnim();
if( !IsDefined(swapAnim) )
{
return;
}
self animMode( "angle deltas" );
self SetFlaggedAnimKnobAllRestart( "weapon swap", swapAnim, %body, 1, .1, 1 );
self DoNoteTracks( "weapon swap" );
if( GetDvarInt( #"aiQuadrantSwitch") == 2 )
{
pulloutAnim = getWeaponPulloutAnim();
if( IsDefined(swapAnim) )
{
self SetFlaggedAnimKnobAllRestart( "weapon swap", pulloutAnim, %body, 1, .1, 1 );
self DoNoteTracks( "weapon swap" );
}
}
self ClearAnim(%weapon_switch, 0.2);
self.a.weapon_switch_time = gettime();
self.a.weapon_switch_for_distance_time = -1;
self notify("weapon_switched");
self maps\_gameskill::didSomethingOtherThanShooting();
}
isEnemyInExplodableVolume()
{
if (!IsDefined(self.enemy))
{
return false;
}
if (IsDefined(self.enemy._explodable_targets) )
{
for (i = 0; i < self.enemy._explodable_targets.size; i++)
{
if (IsDefined(self.enemy._explodable_targets[i]) && self CanSee(self.enemy._explodable_targets[i]))
{
return true;
}
}
}
else if( IsDefined(self.enemy.script_exploder) || self.enemy is_destructible())
{
return true;
}
return false;
}
shouldSwitchWeaponForSituation()
{
self endon( "death" );
secondaryWeaponClass = weaponClass( self getSecondaryWeapon() );
if( isEnemyInExplodableVolume() && secondaryWeaponClass == "rocketlauncher" && WeaponClass(self.weapon) != "rocketlauncher" )
{
return true;
}
return false;
}
setAimingAnims( aim_2, aim_4, aim_6, aim_8 )
{
assert( IsDefined(aim_2) );
assert( IsDefined(aim_4) );
assert( IsDefined(aim_6) );
assert( IsDefined(aim_8) );
self.a.aim_2 = aim_2;
self.a.aim_4 = aim_4;
self.a.aim_6 = aim_6;
self.a.aim_8 = aim_8;
}