#include maps\_utility; #include common_scripts\utility; globalThink() { if ( !isdefined( self.vehicletype ) ) return; isHelicopter = false; if ( self.vehicletype == "hind" ) { isHelicopter = true; } if ( ( self.vehicletype == "cobra" ) || ( self.vehicletype == "cobra_player" ) ) { self thread attachMissiles( "cobra_Hellfire", "cobra_Sidewinder" ); isHelicopter = true; } if ( !isHelicopter ) return; level thread flares_think( self ); level thread maps\_helicopter_ai::evasive_think( self ); if ( getdvar( "cobrapilot_wingman_enabled" ) == "1" ) { if ( isdefined( self.script_wingman ) ) { level.wingman = self; level thread maps\_helicopter_ai::wingman_think( self ); } } } flares_think( vehicle ) { vehicle endon( "death" ); while ( vehicle.health > 0 ) { if ( isdefined( vehicle.playercontrolled ) ) { if ( ( !vehicle.pilot buttonPressed( level.flareButton1 ) ) && ( !vehicle.pilot buttonPressed( level.flareButton2 ) ) ) { wait 0.05; continue; } } else { vehicle waittill( "incomming_missile", eMissile ); if ( !isdefined( eMissile ) ) continue; //sometimes dont drop flares if ( randomint( 3 ) == 0 ) continue; wait randomfloatrange( 0.5, 1.0 ); } flares_fire( vehicle ); wait 0.05; if ( !isdefined( vehicle.playercontrolled ) ) wait 3.0; } } flares_fire_burst( vehicle, fxCount, flareCount, flareTime ) { assert( isdefined( level.flare_fx[ vehicle.vehicletype ] ) ); assert( fxCount >= flareCount ); for ( i = 0 ; i < fxCount ; i++ ) { playfx( level.flare_fx[ vehicle.vehicletype ], vehicle getTagOrigin( "tag_flare" ) ); if ( isdefined( vehicle.playercontrolled ) ) { level.stats[ "flares_used" ]++ ; if ( getdvar( "cobrapilot_sounds_enabled" ) == "1" ) vehicle.pilot playLocalSound( "weap_flares_fire" ); } if ( i <= flareCount - 1 ) thread flares_redirect_missiles( vehicle, flareTime ); wait 0.1; } } flares_fire( vehicle ) { vehicle endon( "death" ); if ( isdefined( vehicle.playercontrolled ) ) { flareTime = 1.0; while ( ( vehicle.pilot buttonPressed( level.flareButton1 ) ) || ( vehicle.pilot buttonPressed( level.flareButton2 ) ) ) { flares_fire_burst( vehicle, 1, 1, flareTime ); flareTime = flareTime + 1.0; if ( flareTime > 5.0 ) flareTime = 5.0; } } else { flares_fire_burst( vehicle, 8, 1, 5.0 ); } } flares_redirect_missiles( vehicle, flareTime ) { vehicle notify( "flares_out" ); vehicle endon( "death" ); vehicle endon( "flares_out" ); if ( !isdefined( flareTime ) ) flareTime = 5.0; // create a script_origin at the flares location and move it down with gravity vec = flares_get_vehicle_velocity( vehicle ); flare = spawn( "script_origin", vehicle getTagOrigin( "tag_flare" ) ); flare movegravity( vec, flareTime ); if ( !isdefined( vehicle.incomming_Missiles ) ) return; // redirect all incomming missiles to the new flares for ( i = 0 ; i < vehicle.incomming_Missiles.size ; i++ ) vehicle.incomming_Missiles[ i ] Missile_SetTargetEnt( flare ); // wait for flares to burn out wait flareTime; if ( !isdefined( vehicle.script_targetoffset_z ) ) vehicle.script_targetoffset_z = 0; offset = ( 0, 0, vehicle.script_targetoffset_z ); // when the flares burn out redirect missiles to the main target again ( if missile is still alive ) if ( !isdefined( vehicle.incomming_Missiles ) ) return; for ( i = 0 ; i < vehicle.incomming_Missiles.size ; i++ ) vehicle.incomming_Missiles[ i ] Missile_SetTargetEnt( vehicle, offset ); } flares_get_vehicle_velocity( vehicle ) { org1 = vehicle.origin; wait 0.05; vec = ( vehicle.origin - org1 ); return vector_multiply( vec, 20 ); } missile_deathWait( eMissile, eMissile_Target ) { eMissile_Target endon( "death" ); eMissile waittill( "death" ); if ( !isdefined( eMissile_Target.incomming_Missiles ) ) return; eMissile_Target.incomming_Missiles = array_remove( eMissile_Target.incomming_Missiles, eMissile ); } getEnemyTarget( fRadius, iFOVcos, getAITargets, doSightTrace, getVehicleTargets, randomizeTargetArray, aExcluders ) { if ( !isdefined( getAITargets ) ) getAITargets = false; if ( !isdefined( doSightTrace ) ) doSightTrace = false; if ( !isdefined( getVehicleTargets ) ) getVehicleTargets = true; if ( !isdefined( randomizeTargetArray ) ) randomizeTargetArray = false; // look for a vehicle target eTargets = []; eClosestValidTarget = undefined; enemyTeam = common_scripts\utility::get_enemy_team( self.script_team ); possibleTargets = []; //prof_begin( "cobrapilot_ai" ); if ( getVehicleTargets ) { assert( isdefined( level.vehicles[ enemyTeam ] ) ); for ( i = 0 ; i < level.vehicles[ enemyTeam ].size ; i++ ) possibleTargets[ possibleTargets.size ] = level.vehicles[ enemyTeam ][ i ]; } if ( getAITargets ) { enemyAI = getaiarray( enemyTeam ); for ( i = 0 ; i < enemyAI.size ; i++ ) { if( isdefined( enemyAI[ i ].ignored_by_attack_heli ) ) continue; possibleTargets[ possibleTargets.size ] = enemyAI[ i ]; } if ( enemyTeam == "allies" ) { for ( i = 0; i < level.players.size; i++ ) { possibleTargets[ possibleTargets.size ] = level.players[ i ]; } } } if ( isdefined( aExcluders ) ) possibleTargets = array_exclude( possibleTargets, aExcluders ); if ( randomizeTargetArray ) possibleTargets = array_randomize( possibleTargets ); forwardvec = anglestoforward( self.angles ); for ( i = 0 ; i < possibleTargets.size ; i++ ) { // threatbias - if this is an ignored group then dont consider this target if ( ( isSentient( possibleTargets[ i ] ) ) && ( isSentient( self ) ) && ( self getThreatBiasGroup() != "" ) ) { bias = getThreatBias( possibleTargets[ i ] getThreatBiasGroup(), self getThreatBiasGroup() ); if ( bias <= -1000000 ) continue; } // check if the target is within range if ( isdefined( fRadius ) && ( fRadius > 0 ) ) { if ( distance( self.origin, possibleTargets[ i ].origin ) > fRadius ) continue; } // check if the target is within fov if ( isdefined( iFOVcos ) ) { normalvec = vectorNormalize( possibleTargets[ i ].origin - ( self.origin ) ); vecdot = vectordot( forwardvec, normalvec ); if ( vecdot <= iFOVcos ) continue; } // check if a sight trace passes if ( doSightTrace ) { sightTracePassed = false; if ( isAi( possibleTargets[ i ] ) ) TraceZoffset = 48; else TraceZoffset = 150; sightTracePassed = sighttracepassed( self.origin, possibleTargets[ i ].origin + ( 0, 0, TraceZoffset ), false, self ); if ( !sightTracePassed ) continue; } eTargets[ eTargets.size ] = possibleTargets[ i ]; } //prof_end( "cobrapilot_ai" ); self notify( "gunner_new_target" ); // return if no targets were found if ( eTargets.size == 0 ) return eClosestValidTarget; // if only one target was found return it if ( eTargets.size == 1 ) return eTargets[ 0 ]; // return the closest of the targets //prof_begin( "cobrapilot_ai" ); theTarget = getClosest( self.origin, eTargets ); //prof_end( "cobrapilot_ai" ); return theTarget; } shootEnemyTarget_Bullets( eTarget ) { self endon( "death" ); self endon( "mg_off" ); eTarget endon( "death" ); self endon( "gunner_new_target" ); if ( isdefined( self.playercontrolled ) ) self endon( "gunner_stop_firing" ); eTargetOffset = ( 0, 0, 0 ); if ( isdefined( eTarget.script_targetoffset_z ) ) eTargetOffset += ( 0, 0, eTarget.script_targetoffset_z ); else if ( isSentient( eTarget ) ) eTargetOffset = ( 0, 0, 32 ); self setTurretTargetEnt( eTarget, eTargetOffset ); while ( self.health > 0 ) { randomShots = randomintrange( 1, 25 ); if ( getdvar( "cobrapilot_debug" ) == "1" ) iprintln( "randomShots = " + randomShots ); for ( i = 0 ; i < randomShots ; i++ ) { // if the vehicle firing the bullets is the players vehicle we have to switch to the 20mm gun if ( isdefined( self.playercontrolled ) ) { if ( ( isdefined( level.cobraWeapon ) ) && ( level.cobraWeapon.size > 0 ) ) self setVehWeapon( level.GunnerWeapon ); } self thread shootEnemyTarget_Bullets_DebugLine( self, "tag_turret", eTarget, eTargetOffset, ( 1, 1, 0 ), 0.05 ); self fireWeapon( "tag_flash" ); // then switch it back to the players selection after the shots are fired if ( isdefined( self.playercontrolled ) ) self setVehWeapon( level.cobraWeapon[ self.pilot.currentWeapon ].v[ "weapon" ] ); wait 0.05; } wait randomFloatRange( 0.25, 2.5 ); } } shootEnemyTarget_Bullets_DebugLine( eStartEnt, eStartEntTag, eTarget, eTargetOffset, color, timer ) { if ( getdvar( "cobrapilot_debug" ) != "1" ) return; if ( !isdefined( color ) ) color = ( 0, 0, 0 ); eTarget endon( "death" ); self endon( "gunner_new_target" ); assert( isdefined( eStartEntTag ) ); if ( !isdefined( eTargetOffset ) ) eTargetOffset = ( 0, 0, 0 ); if ( isdefined( timer ) ) { timer = gettime() + ( timer * 1000 ); while ( gettime() < timer ) { line( eStartEnt getTagOrigin( eStartEntTag ), eTarget.origin + eTargetOffset, color ); wait 0.05; } } else { for ( ;; ) { line( eStartEnt getTagOrigin( eStartEntTag ), eTarget.origin + eTargetOffset, color ); wait 0.05; } } } attachMissiles( weapon1, weapon2, weapon3, weapon4 ) { self.hasAttachedWeapons = true; assert( isdefined( weapon1 ) ); weapon = []; weapon[ 0 ] = weapon1; if ( isdefined( weapon2 ) ) weapon[ 1 ] = weapon2; if ( isdefined( weapon3 ) ) weapon[ 2 ] = weapon3; if ( isdefined( weapon4 ) ) weapon[ 3 ] = weapon4; /* for( i = 0 ; i < weapon.size ; i++ ) { for( k = 0 ; k < level.cobra_weapon_tags[weapon[i]].size ; k++ ) { self attach( level.cobra_missile_models[weapon[i]], level.cobra_weapon_tags[weapon[i]][k] ); } } */ for ( i = 0 ; i < weapon.size ; i++ ) { for ( k = 0 ; k < level.cobra_weapon_tags[ weapon[ i ] ].size ; k++ ) { self attach( level.cobra_missile_models[ weapon[ i ] ], level.cobra_weapon_tags[ weapon[ i ] ][ k ] ); } } } fire_missile( sMissileType, iShots, eTarget, fDelay ) { if ( !isdefined( iShots ) ) iShots = 1; assert( self.health > 0 ); weaponName = undefined; weaponShootTime = undefined; defaultWeapon = "cobra_20mm"; tags = []; switch( sMissileType ) { case "f15_missile": weaponName = "cobra_Sidewinder"; tags[ 0 ] = "le_side_wing_jnt"; tags[ 1 ] = "ri_side_wing_jnt"; break; case "mi28_seeker": weaponName = "cobra_seeker"; tags[ 0 ] = "tag_store_L_1_a"; tags[ 1 ] = "tag_store_R_1_a"; tags[ 2 ] = "tag_store_L_2_a"; tags[ 3 ] = "tag_store_R_2_a"; break; case "ffar": weaponName = "cobra_FFAR"; tags[ 0 ] = "tag_store_r_2"; break; case "seeker": weaponName = "cobra_seeker"; tags[ 0 ] = "tag_store_r_2"; break; case "ffar_bog_a_lite": weaponName = "cobra_FFAR_bog_a_lite"; tags[ 0 ] = "tag_store_r_2"; break; case "ffar_airlift": weaponName = "cobra_FFAR_airlift"; tags[ 0 ] = "tag_store_L_wing"; tags[ 1 ] = "tag_store_R_wing"; break; case "ffar_airlift_nofx": weaponName = "cobra_FFAR_airlift_nofx"; tags[ 0 ] = "tag_store_L_wing"; tags[ 1 ] = "tag_store_R_wing"; break; case "cobra_zippy": weaponName = "zippy_rockets"; tags[ 0 ] = "tag_store_L_wing"; tags[ 1 ] = "tag_store_R_wing"; break; case "cobra_turret": weaponName = "hind_turret_penetration"; tags[ 0 ] = "tag_store_L_wing"; tags[ 1 ] = "tag_store_R_wing"; break; case "ffar_hind": defaultWeapon = "hind_turret"; weaponName = "hind_FFAR"; tags[ 0 ] = "tag_missile_left"; tags[ 1 ] = "tag_missile_right"; break; case "hind_zippy": defaultWeapon = "hind_turret"; weaponName = "zippy_rockets"; tags[ 0 ] = "tag_missile_left"; tags[ 1 ] = "tag_missile_right"; break; case "ffar_hind_nodamage": defaultWeapon = "hind_turret"; weaponName = "hind_FFAR_nodamage"; tags[ 0 ] = "tag_missile_left"; tags[ 1 ] = "tag_missile_right"; break; case "ffar_mi28_village_assault": defaultWeapon = "hind_turret"; weaponName = "mi28_ffar_village_assault"; tags[ 0 ] = "tag_store_L_2_a"; tags[ 1 ] = "tag_store_R_2_a"; tags[ 2 ] = "tag_store_L_2_b"; tags[ 3 ] = "tag_store_R_2_b"; tags[ 4 ] = "tag_store_L_2_c"; tags[ 5 ] = "tag_store_R_2_c"; tags[ 6 ] = "tag_store_L_2_d"; tags[ 7 ] = "tag_store_R_2_d"; break; case "ffar_co_rescue": weaponName = "cobra_FFAR_bog_a_lite"; tags[ 0 ] = "tag_store_R_2_a"; tags[ 1 ] = "tag_store_L_2_a"; break; default: assertMsg( "Invalid missile type specified." ); break; } assert( isdefined( weaponName ) ); assert( tags.size > 0 ); weaponShootTime = weaponfiretime( weaponName ); assert( isdefined( weaponShootTime ) ); nextMissileTag = -1; for ( i = 0 ; i < iShots ; i++ ) { nextMissileTag++ ; if ( nextMissileTag >= tags.size ) nextMissileTag = 0; if ( sMissileType == "ffar_mi28_village_assault" ) { if ( isdefined( eTarget ) && isdefined( eTarget.origin ) ) { magicBullet( weaponName, self getTagOrigin( tags[ nextMissileTag ] ), eTarget.origin ); if ( isdefined( level._effect[ "ffar_mi28_muzzleflash" ] ) ) playfxontag( getfx( "ffar_mi28_muzzleflash" ), self, tags[ nextMissileTag ] ); thread delayed_earthquake( 0.1, 0.5, 0.2, eTarget.origin, 1600 ); } } else { self setVehWeapon( weaponName ); if ( isdefined( eTarget ) ) { eMissile = self fireWeapon( tags[ nextMissileTag ], eTarget ); if ( sMissileType == "ffar" ) eMissile thread missileLoseTarget( 0.1 ); if ( sMissileType == "ffar_bog_a_lite" ) eMissile thread missileLoseTarget( 0.1 ); if ( sMissileType == "ffar_airlift" ) eMissile thread missileLoseTarget( 0.1 ); } else eMissile = self fireWeapon( tags[ nextMissileTag ] ); } if ( i < iShots - 1 ) wait weaponShootTime; if ( isdefined( fDelay ) ) wait( fDelay ); } self setVehWeapon( defaultWeapon ); } delayed_earthquake( fDelay, scale, duration, source, fRadius ) { wait fDelay; earthquake( scale, duration, source, fRadius ); } missileLoseTarget( fDelay ) { self endon( "death" ); wait fDelay; if ( isdefined( self ) ) self Missile_ClearTarget(); }