#include maps\_utility; #include common_scripts\utility; #include maps\_hud_util; init() { //should make hellfires no do friendly fire level.no_friendly_fire_splash_damage = true; if ( !isdefined( level.min_time_between_uav_launches ) ) { level.min_time_between_uav_launches = 12 * 1000; } level.last_uav_launch_time = 0 - level.min_time_between_uav_launches; // level.last_uav_offline_time = 0; level.uav_radio_offline_called = false; PreCacheItem( "remote_missile_detonator" ); PreCacheItem( "remote_missile" ); PreCacheShader( "veh_hud_target" ); PreCacheShader( "veh_hud_target_offscreen" ); PreCacheShader( "veh_hud_missile_flash" ); PreCacheShader( "ac130_overlay_grain" ); PreCacheShader( "remotemissile_infantry_target" ); PreCacheShader( "hud_fofbox_self_sp" ); PreCacheShader( "dpad_killstreak_hellfire_missile_inactive" ); precacheString( &"HELLFIRE_DRONE_VIEW" ); precacheString( &"HELLFIRE_MISSILE_VIEW" ); precacheString( &"HELLFIRE_FIRE" ); // Predator Drone has been destroyed. add_hint_string( "hint_predator_drone_destroyed", &"HELLFIRE_DESTROYED", ::should_break_destroyed ); // Predator Drone is unavailable. add_hint_string( "hint_predator_drone_4", &"HELLFIRE_USE_DRONE", ::should_break_use_drone ); add_hint_string( "hint_predator_drone_2", &"HELLFIRE_USE_DRONE_2", ::should_break_use_drone ); add_hint_string( "hint_predator_drone_not_available", &"HELLFIRE_DRONE_NOT_AVAILABLE", ::should_break_available ); // array_thread( level.players, ::RemoteMissileDetonatorNotify ); VisionSetMissilecam( "missilecam" ); SetSavedDvar( "missileRemoteSpeedUp", "1000" ); SetSavedDvar( "missileRemoteSpeedTargetRange", "6000 12000" ); mapname = GetDvar( "mapname" ); if ( mapname == "zzz" ) { } else if ( mapname == "raymetest" ) { SetSavedDvar( "missileRemoteSpeedUp", "500" ); SetSavedDvar( "missileRemoteSpeedTargetRange", "3000 6000" ); } add_global_spawn_function( "axis", ::missile_kill_ai ); flag_init( "uav_reloading" ); flag_init( "uav_collecting_stats" ); flag_init( "uav_enabled" ); flag_set( "uav_enabled" ); } should_break_use_drone() { break_hint = false; if ( isdefined( level.uav_is_destroyed ) ) { break_hint = true; } if ( !isalive( level.uav ) ) { break_hint = true; } if ( isdefined( self.is_flying_missile ) ) { break_hint = true; } // Sniper Fi Support if ( flag_exist( "wave_wiped_out" ) && flag( "wave_wiped_out" ) ) { break_hint = true; } if ( self ent_flag_exist( "coop_downed" ) && self ent_flag( "coop_downed" ) ) { break_hint = true; } if( self getCurrentWeapon() == "remote_missile_detonator" ) { break_hint = true; } return break_hint; } init_radio_dialogue() { if ( !IsDefined( level.scr_radio ) ) { level.scr_radio = []; } level.uav_radio_initialized = true; // Offline / Online level.scr_radio[ "uav_reloading" ] = "cont_cmt_rearmhellfires"; level.scr_radio[ "uav_offline" ] = "cont_cmt_hellfiresoffline"; level.scr_radio[ "uav_online" ] = "cont_cmt_hellfireonline"; level.scr_radio[ "uav_online_repeat" ] = "cont_cmt_repeatonline"; level.scr_radio[ "uav_down" ] = "cont_cmt_uavdown"; // AI Kills level.scr_radio[ "uav_multi_kill" ] = "cont_cmt_mutlipleconfirmed"; level.scr_radio[ "uav_multi_kill2" ] = "cont_cmt_fivepluskias"; level.scr_radio[ "uav_few_kills" ] = "cont_cmt_theyredown"; level.scr_radio[ "uav_3_kills" ] = "cont_cmt_3kills"; level.scr_radio[ "uav_1_kill" ] = "cont_cmt_hesdown"; // vehicle kills level.scr_radio[ "uav_btr_kill" ] = "cont_cmt_mutlipleconfirmed"; level.scr_radio[ "uav_few_kills" ] = "cont_cmt_theyredown"; level.scr_radio[ "uav_3_kills" ] = "cont_cmt_3kills"; level.scr_radio[ "uav_1_kill" ] = "cont_cmt_hesdown"; level.scr_radio[ "uav_multi_vehicle_kill" ] = "cont_cmt_goodhitvehicles"; level.scr_radio[ "uav_multi_vehicle_kill2" ] = "cont_cmt_goodeffectkia"; level.scr_radio[ "uav_helo_kill" ] = "cont_cmt_directhitshelo"; level.scr_radio[ "uav_btr_kill" ] = "cont_cmt_btrdestroyed"; level.scr_radio[ "uav_truck_kill" ] = "cont_cmt_goodkilltruck"; level.scr_radio[ "uav_jeep_kill" ] = "cont_cmt_directhitjeep"; level.scr_radio[ "uav_direct_hit" ] = "cont_cmt_directhit"; } is_radio_defined( alias ) { return IsDefined( level.scr_radio[ alias ] ) || IsDefined( level.scr_radio[ alias + "_variant" ] ); } should_break_available() { if ( IsDefined( level.uav_is_not_available ) ) return false; else return true; } should_break_destroyed() { if ( IsDefined( level.uav_is_destroyed ) ) return false; else return true; } enable_uav( do_radio, restore ) { if ( !IsDefined( do_radio ) ) { do_radio = true; } if ( !flag( "uav_enabled" ) ) { flag_set( "uav_enabled" ); if ( !flag( "uav_reloading" ) && do_radio ) { thread remotemissile_radio( "uav_online" ); } } if ( IsDefined( restore ) ) { restore_uav_weapon( restore ); } } disable_uav( do_radio, remove ) { if ( !IsDefined( do_radio ) ) { do_radio = true; } if ( flag( "uav_enabled" ) ) { flag_clear( "uav_enabled" ); if ( !flag( "uav_reloading" ) && do_radio ) { thread remotemissile_radio( "uav_offline" ); } } if ( IsDefined( remove ) ) { remove_uav_weapon(); } } restore_uav_weapon( restore ) { if ( IsDefined( level.uav_is_destroyed ) ) { return; } if ( IsString( restore ) ) { weapon = restore; } else if ( IsDefined( self.uav_weaponname ) ) { weapon = self.uav_weaponname; } else { return; } if ( !self HasWeapon( weapon ) ) { return; } self SetWeaponHudIconOverride( "actionslot" + self get_remotemissile_actionslot(), "none" ); self SetActionSlot( self get_remotemissile_actionslot(), "weapon", weapon ); } remove_uav_weapon() { self SetWeaponHudIconOverride( "actionslot" + self get_remotemissile_actionslot(), "dpad_killstreak_hellfire_missile_inactive" ); self SetActionSlot( self get_remotemissile_actionslot(), "" ); } is_remote_missile_weapon( weap ) { if ( !IsDefined( weap ) ) { return false; } if ( weap == "remote_missile_detonator" ) { return true; } if ( weap == "remote_missile_detonator_finite" ) { return true; } return false; } give_remotemissile_weapon( weapon_name ) { self set_remotemissile_actionslot(); self SetActionSlot( self get_remotemissile_actionslot(), "weapon", weapon_name ); self GiveWeapon( weapon_name ); self thread RemoteMissileDetonatorNotify(); } // Sets the proper dpad depending if they have the claymore or not set_remotemissile_actionslot() { if ( !self HasWeapon( "claymore" ) ) { // Move the claymore (since we do not have it yet) to the down dpad self.remotemissile_actionslot = 4; } else { self.remotemissile_actionslot = 2; } } get_remotemissile_actionslot() { AssertEx( IsDefined( self.remotemissile_actionslot ), "self.remotemissile_actionslot is undefined, you need to use the give_remotemissile_weapon() function in here to give the player the weapon properly." ); return self.remotemissile_actionslot; } remotemissile_weapon_change() { self.using_uav = false; while ( 1 ) { self waittill( "weapon_change", weap ); if ( is_remote_missile_weapon( weap ) ) { self.using_uav = true; if ( IsDefined( level.uav_is_destroyed ) ) { thread remotemissile_offline( false, "uav_down" ); self SwitchToWeapon( self.last_weapon ); self.using_uav = false; continue; } if ( self ent_flag_exist( "coop_downed" ) && self ent_flag( "coop_downed" ) ) { self SwitchBackToMainWeapon(); self.using_uav = false; continue; } self.uav_weaponname = weap; self thread cancel_on_player_damage(); if ( IsDefined( level.remote_missile_hide_stuff_func ) ) { [[ level.remote_missile_hide_stuff_func ]](); } level.uav_user = self; level.uav_killstats = []; UAVRemoteLauncherSequence( self, weap ); level.uav_user = undefined; self.using_uav = false; if ( IsDefined( level.remote_missile_show_stuff_func ) ) { [[ level.remote_missile_show_stuff_func ]](); } thread remotemissile_reload(); } } } RemoteMissileDetonatorNotify() { Assert( self.classname == "player" ); self NotifyOnPlayerCommand( "switch_to_remotemissile", "+actionslot " + self get_remotemissile_actionslot() ); self thread remotemissile_weapon_change(); for ( ;; ) { self waittill( "switch_to_remotemissile" ); if ( self.using_uav ) { continue; } if ( !is_remote_missile_weapon( self GetCurrentWeapon() ) ) { self.last_weapon = self GetCurrentWeapon(); } if ( IsDefined( level.uav_is_destroyed ) ) { thread remotemissile_offline( false, "uav_down" ); } else if ( flag( "uav_reloading" ) || !flag( "uav_enabled" ) ) { thread remotemissile_offline( true ); } } } remotemissile_offline( extra_check, alias ) { if ( !IsDefined( alias ) ) { alias = "uav_offline"; } curr_time = GetTime(); // Only use extra_check if you don't want the dialogue to happen just before the hellfire "online" is about to // play if ( extra_check && ( ( level.last_uav_launch_time + level.min_time_between_uav_launches ) - curr_time < 2000 ) || level.min_time_between_uav_launches < 5000 ) { // These 2 checks are specific to levels. // SO_ROOFTOP_CONTINGENCY needs dialogue if out of ammo. // All other levels need uav_is_destroyed if ( !IsDefined( level.uav_is_destroyed ) && ( IsDefined( self.uav_weaponname ) && self GetWeaponAmmoClip( self.uav_weaponname ) > 0 ) ) { return; } } if( flag( "uav_reloading" ) ) { if( isdefined( level.scr_radio[ "uav_reloading" ] ) ) { alias = "uav_reloading"; } } // if ( !flag( "uav_collecting_stats" ) && curr_time > level.last_uav_offline_time + 1000 ) if ( !flag( "uav_collecting_stats" ) && !level.uav_radio_offline_called ) { level.uav_radio_offline_called = true; remotemissile_radio( alias ); level.uav_radio_offline_called = false; } } remotemissile_reload() { level endon( "stop_uav_reload" ); level endon( "special_op_terminated" ); // Wait for reload if ( flag( "uav_reloading" ) ) { if ( IsDefined( level.uav_is_destroyed ) ) { return; } remove_uav_weapon(); if ( flag( "uav_collecting_stats" ) ) { level waittill( "uav_collecting_stats" ); play_kills_dialogue(); } if ( IsDefined( level.uav_is_destroyed ) ) { return; } // Make uav_user undefined so missile_kill_ai returns immediately. level.uav_user = undefined; //z: dont want to hear hellfire off line after each shot // Only do the dialogue if we have enough time between reloads. //if ( level.min_time_between_uav_launches > 5000 ) //{ // thread remotemissile_offline( false ); //} // Waiting for the flag_clear() notify if ( flag( "uav_reloading" ) ) { level waittill( "uav_reloading" ); } if ( IsDefined( level.uav_is_destroyed ) ) { return; } if ( !flag( "uav_enabled" ) ) { return; } if ( self GetWeaponAmmoClip( self.uav_weaponname ) < 1 ) { disable_uav(); return; } restore_uav_weapon(); thread remotemissile_radio( "uav_online" ); thread remotemissile_radio_reminder(); } } remotemissile_radio_reminder() { level notify( "stop_remotemissile_radio_reminder" ); level endon( "special_op_terminated" ); level endon( "starting_predator_drone_control" ); level endon( "stop_remotemissile_radio_reminder" ); while( 1 ) { wait( 7 + RandomInt( 4 ) ); if ( flag_exist( "special_op_terminated" ) && flag( "special_op_terminated" ) ) { return; } if ( IsDefined( level.uav_is_destroyed ) ) { return; } if ( flag( "uav_reloading" ) ) { return; } if ( !flag( "uav_enabled" ) ) { return; } remotemissile_radio( "uav_online_repeat" ); wait( 15 + RandomInt( 10 ) ); if ( flag_exist( "special_op_terminated" ) && flag( "special_op_terminated" ) ) { return; } if ( IsDefined( level.uav_is_destroyed ) ) { return; } if ( IsDefined( level.no_remote_missile_reminders ) ) { return; } remotemissile_radio( "uav_online" ); self thread display_hint_timeout( "hint_predator_drone_" + self get_remotemissile_actionslot(), 6 ); } } play_kills_dialogue() { if ( IsDefined( level.dont_use_global_uav_kill_dialog ) ) return; if ( !IsDefined( level.uav_radio_initialized ) ) { return; } // "Good hit. Multiple vehicles destroyed." level.scr_radio[ "multi_vehicle_kill" ] = "cont_cmt_goodhitvehicles"; // "Good effect on target. Multiple enemy vehicles KIA." level.scr_radio[ "multi_vehicle_kill2" ] = "cont_cmt_goodeffectkia"; // "Direct hit on the enemy helo. Nice shot Roach." level.scr_radio[ "helo_kill" ] = "cont_cmt_directhitshelo"; // "Good effect on target. BTR destroyed." level.scr_radio[ "btr_kill" ] = "cont_cmt_btrdestroyed"; // "Good kill. Truck destroyed." level.scr_radio[ "truck_kill" ] = "cont_cmt_goodkilltruck"; // "Direct hit on that jeep." level.scr_radio[ "jeep_kill" ] = "cont_cmt_directhitjeep"; // "Direct hit." level.scr_radio[ "direct_hit" ] = "cont_cmt_directhit"; // "Five plus KIAs. Good hit. Good hit. level.scr_radio[ "multi_kill2" ] = "cont_cmt_fivepluskias"; // "Multiple confirmed kills. Nice work." level.scr_radio[ "multi_kill" ] = "cont_cmt_mutlipleconfirmed"; // "They're down." level.scr_radio[ "few_kills" ] = "cont_cmt_theyredown"; // "Good hit. Looks like at least three kills." level.scr_radio[ "3_kills" ] = "cont_cmt_3kills"; // "He's down." level.scr_radio[ "1_kill" ] = "cont_cmt_hesdown"; ai_alias = undefined; ai_kills = 0; if ( IsDefined( level.uav_killstats[ "ai" ] ) ) { ai_kills = level.uav_killstats[ "ai" ]; } if ( ai_kills > 5 ) { ai_alias = "uav_multi_kill"; if ( is_radio_defined( "uav_multi_kill2" ) && cointoss() ) { ai_alias = "uav_multi_kill2"; } } else if ( ai_kills >= 3 ) { ai_alias = "uav_3_kills"; } else if ( ai_kills > 1 ) { ai_alias = "uav_few_kills"; } else if ( ai_kills > 0 ) { ai_alias = "uav_1_kill"; } vehicle_alias = undefined; btr_kills = 0; vehicle_kills = 0; btr_kills = 0; helo_kills = 0; jeep_kills = 0; truck_kills = 0; foreach ( index, kills in level.uav_killstats ) { if ( index == "ai" ) { continue; } if ( kills > 0 ) { vehicle_kills = vehicle_kills + kills; if ( index == "btr" ) { btr_kills = kills; } else if ( index == "helo" ) { helo_kills = kills; } else if ( index == "jeep" ) { jeep_kills = kills; } else if ( index == "truck" ) { truck_kills = kills; } } } alias = ai_alias; if ( btr_kills > 0 ) { alias = "uav_btr_kill"; } else if ( helo_kills > 0 ) { alias = "uav_helo_kill"; } else if ( vehicle_kills > 1 ) { alias = "uav_multi_vehicle_kill"; if ( is_radio_defined( "uav_multi_vehicle_kill2" ) && cointoss() ) { alias = "uav_multi_vehicle_kill2"; } } else if ( jeep_kills > 0 ) { alias = "uav_jeep_kill"; if ( ai_kills > 2 && ai_kills <= 5 && is_radio_defined( "uav_direct_hit" ) && cointoss() ) { alias = "uav_direct_hit"; } } else if ( truck_kills > 0 ) { alias = "uav_truck_kill"; if ( ai_kills > 2 && ai_kills <= 5 && is_radio_defined( "uav_direct_hit" ) && cointoss() ) { alias = "uav_direct_hit"; } } if ( !IsDefined( alias ) ) { return; } if ( flag_exist( "special_op_terminated" ) && flag( "special_op_terminated" ) ) { return; } remotemissile_radio( alias ); level notify( "remote_missile_kill_dialogue" ); } set_variant_remotemissile_radio( alias ) { if ( IsDefined( level.scr_radio[ alias + "_variant" ] ) && IsArray( level.scr_radio[ alias + "_variant" ] ) ) { level.scr_radio[ alias ] = level.scr_radio[ alias + "_variant" ][ RandomInt( level.scr_radio[ alias + "_variant" ].size ) ]; } } remotemissile_radio( alias ) { if ( !IsDefined( level.uav_radio_initialized ) ) { return; } if ( IsDefined( level.uav_radio_disabled ) && level.uav_radio_disabled ) { return; } if ( !is_radio_defined( alias ) ) { return; } if ( flag_exist( "special_op_terminated" ) && flag( "special_op_terminated" ) ) { return; } set_variant_remotemissile_radio( alias ); radio_dialogue( alias ); } cancel_on_player_damage() { self.took_damage = false; //self waittill( "damage" ); self waittill_any( "damage", "dtest", "force_out_of_uav" ); self.took_damage = true; } text_TitleCreate() { level.text1 = self createClientFontString( "objective", 2.0 ); level.text1 setPoint( "CENTER", undefined, 0, -175 ); } text_TitleSetText( text ) { level.text1 SetText( text ); } text_TitleFadeout() { level.text1 FadeOverTime( 0.25 ); level.text1.alpha = 0; } text_TitleDestroy() { if ( !IsDefined( level.text1 ) ) return; level.text1 Destroy(); level.text1 = undefined; } display_wait_to_fire( time_till_reload ) { text_NoticeDestroy(); // MISSILE RELOADED IN: self text_LabelCreate( &"HELLFIRE_RELOADING_WITH_TIME", time_till_reload ); wait( 1 ); text_NoticeDestroy(); } text_LabelCreate( text, time ) { level.text2 = self createClientFontString( "objective", 1.85 ); level.text2 SetPoint( "CENTER", undefined, 0, -120 ); level.text2.label = text; level.text2 SetValue( time ); level.text2.color = ( 0.85, 0.85, 0.85 ); level.text2.alpha = 0.75; } text_NoticeCreate( text ) { level.text2 = self createClientFontString( "objective", 1.85 ); level.text2 SetPoint( "CENTER", undefined, 0, -120 ); level.text2 SetText( text ); level.text2.color = ( 0.85, 0.85, 0.85 ); level.text2.alpha = 0.75; } text_NoticeFadeout() { if ( !IsDefined( level.text2 ) ) return; level.text2 FadeOverTime( 0.25 ); level.text2.alpha = 0; } text_NoticeDestroy() { if ( !IsDefined( level.text2 ) ) return; level.text2 Destroy(); level.text2 = undefined; } WaitWithAbortOnDamage( time ) { finishTime = GetTime() + ( time * 1000 ); while ( GetTime() < finishTime ) { if ( self.took_damage ) { return false; } if ( IsDefined( level.uav_is_destroyed ) ) { return false; } if ( !flag( "uav_enabled" ) ) { return false; } wait 0.05; } return true; } NotifyOnMissileDeath( missile ) { timeWeFired = GetTime(); level.remoteMissileFireTime = timeWeFired; if ( IsDefined( missile ) ) { level.remoteMissile = missile; missile waittill( "death" ); } //defensive check; make sure we're this is still the latest remote missile if ( IsDefined( level.remoteMissileFireTime ) && ( level.remoteMissileFireTime == timeWeFired ) ) { level notify( "remote_missile_exploded" ); level.remoteMissile = undefined; } level delayThread( 0.2, ::send_notify, "delayed_remote_missile_exploded" ); } AbortLaptopSwitch( player ) { player VisionSetNakedForPlayer( level.lvl_visionset, 0.5 ); player VisionSetThermalForPlayer( level.visionThermalDefault, 0.5 ); player SwitchBackToMainWeapon(); player FreezeControls( false ); player EnableOffhandWeapons(); level.uavTargetEnt = undefined; wait 0.1; HudItemsShow(); } UAVRemoteLauncherSequence( player, weap ) { if ( weap == "remote_missile_detonator" ) { player GiveMaxAmmo( weap ); } level notify( "starting_predator_drone_control" ); delay_switch_into_missile = false; return_to_uav_after_impact = false; level.VISION_BLACK = "black_bw"; if ( !isdefined( level.VISION_UAV ) ) { level.VISION_UAV = "ac130"; } level.VISION_MISSILE = "missilecam"; level.uavPlayerOrigin = player GetOrigin(); level.uavPlayerAngles = player GetPlayerAngles(); player DisableOffhandWeapons(); player FreezeControls( true ); noDamage = player WaitWithAbortOnDamage( 1.0 ); if ( !noDamage ) { AbortLaptopSwitch( player ); return; } trans_time = .25; player VisionSetNakedForPlayer( level.VISION_BLACK, trans_time ); player VisionSetThermalForPlayer( level.VISION_BLACK, trans_time ); HudItemsHide(); if ( IsDefined( level.remote_missile_targets ) && ( level.remote_missile_targets.size > 0 ) ) { foreach ( thing in level.remote_missile_targets ) { if ( !isalive( thing ) ) level.remote_missile_targets = array_remove( level.remote_missile_targets, thing ); } } noDamage = WaitWithAbortOnDamage( trans_time ); if ( !noDamage ) { AbortLaptopSwitch( player ); return; } player.is_controlling_UAV = true; level notify( "player_is_controlling_UAV" ); if( isdefined( level.uav ) ) { if ( is_specialop() ) { level.uav HideOnClient( self ); } else { level.uav Hide(); } } player PlayerLinkWeaponViewToDelta( level.uavRig, "tag_player", 1.0, 4, 4, 4, 4 ); player FreezeControls( false ); player HideViewModel(); wait 0.05; player text_TitleCreate(); // CAMERA: UAV_DRONE_011 text_TitleSetText( &"HELLFIRE_DRONE_VIEW" ); maps\_load::thermal_EffectsOn(); player ThermalVisionOn(); player SetPlayerAngles( level.uavRig GetTagAngles( "tag_origin" ) ); player VisionSetNakedForPlayer( level.lvl_visionset, 0.25 ); player VisionSetThermalForPlayer( level.VISION_UAV, 0.25 ); thread DrawTargetsStart(); wait 0.2; doAttack = WaitForAttackCommand( player ); if ( !doAttack ) { ExitFromCamera_UAV( player, player.took_damage ); return; } level.last_uav_launch_time = GetTime(); thread uav_reload(); level notify( "player_fired_remote_missile" ); missile = FireMissileFromUAVPlayer( player ); missile thread do_physics_impact_on_explosion( player ); if ( delay_switch_into_missile ) { // -MISSILE LAUNCHED- player text_NoticeCreate( &"HELLFIRE_FIRE" ); noDamage = WaitWithAbortOnDamage( 1.2 ); if ( !noDamage ) { ExitFromCamera_UAV( player, true ); return; } text_NoticeFadeout(); DrawTargetsEnd(); //player VisionSetThermalForPlayer( level.VISION_BLACK, 0.25 ); wait 0.25; } player.is_flying_missile = true;// used to break the hint // CAMERA: HELLFIRE text_TitleSetText( &"HELLFIRE_MISSILE_VIEW" ); text_NoticeDestroy(); SwitchBackToMainWeaponFast(); player RemoteCameraSoundscapeOn(); player Unlink(); //player VisionSetThermalForPlayer( level.VISION_MISSILE, 0.5 ); player DisableWeapons(); player CameraLinkTo( missile, "tag_origin" ); player ControlsLinkTo( missile ); noDamage = WaitWithAbortOnDamage( 0.2 ); if ( !noDamage ) { ExitFromCamera_Missile( player, true ); return; } thread DrawTargetsStart(); while ( IsDefined( level.remoteMissile ) ) { wait 0.05; if ( IsDefined( level.uav_is_destroyed ) ) { ExitFromCamera_Missile( player, true ); return; } if ( player.took_damage ) { ExitFromCamera_Missile( player, true ); return; } if ( !flag( "uav_enabled" ) ) { ExitFromCamera_Missile( player, true ); return; } } if ( !isdefined( level.uav ) ) { ExitFromCamera_Missile( player, false ); return; } if ( return_to_uav_after_impact ) { //new - go back to uav to see explosion level.uav Hide(); SetSavedDvar( "cg_fov", 26 ); player.fov_is_altered = true; player.is_flying_missile = undefined; player ControlsUnlink(); player CameraUnlink(); player RemoteCameraSoundscapeOff(); player PlayerLinkWeaponViewToDelta( level.uavRig, "tag_player", 1.0, 4, 4, 4, 4 ); player SetPlayerAngles( level.uavRig GetTagAngles( "tag_origin" ) ); noDamage = WaitWithAbortOnDamage( 2 ); if ( !noDamage ) { ExitFromCamera_UAV( player, player.took_damage ); return; } ExitFromCamera_UAV( player, false ); } else { ExitFromCamera_Missile( player, false ); } } uav_reload() { level endon( "stop_uav_reload" ); flag_set( "uav_reloading" ); wait( level.min_time_between_uav_launches * 0.001 ); flag_clear( "uav_reloading" ); } do_physics_impact_on_explosion( player ) { player.fired_hellfire_missile = true; player waittill( "projectile_impact", weaponName, position, radius ); level thread missile_kills( player ); level.uavTargetPos = position; physicsSphereRadius = 1000; physicsSphereForce = 6.0; Earthquake( .3, 1.4, position, 8000 ); wait 0.1; PhysicsExplosionSphere( position, physicsSphereRadius, physicsSphereRadius / 2, physicsSphereForce ); wait 2; level.uavTargetPos = undefined; player.fired_hellfire_missile = undefined; //level notify ( "player_missile_finished_impact" ); } missile_kills( player ) { flag_set( "uav_collecting_stats" ); // ai_array = GetAIArray( "axis" ); // foreach ( ai in ai_array ) // { // ai thread missile_kill_ai( player ); // } vehicles = getVehicleArray(); foreach ( vehicle in vehicles ) { vehicle thread missile_kill_vehicle( player ); } wait( 1 ); flag_clear( "uav_collecting_stats" ); } missile_kill_ai( attacker ) { if ( !IsDefined( level.uav_radio_initialized ) ) { return; } self waittill( "death", attacker, cause ); if ( !IsDefined( level.uav_user ) ) { return; } if ( !IsDefined( level.uav_killstats[ "ai" ] ) ) { level.uav_killstats[ "ai" ] = 0; } if ( IsDefined( attacker ) && IsDefined( level.uav_user ) ) { if ( attacker == level.uav_user || ( IsDefined( attacker.attacker ) && attacker.attacker == level.uav_user ) ) { level.uav_killstats[ "ai" ]++; if( isplayer( level.uav_user ) && level.uav_killstats[ "ai" ] == 10 ) level.uav_user player_giveachievement_wrapper( "TEN_PLUS_FOOT_MOBILES" ); } } } missile_kill_vehicle( player ) { if ( !IsDefined( level.uav_radio_initialized ) ) { return; } level endon( "delayed_remote_missile_exploded" ); type = undefined; switch( self.vehicletype ) { case "btr80": case "btr80_physics": type = "btr"; break; case "ucav": case "hind": case "mi17": case "mi17_noai": case "mi17_bulletdamage": type = "helo"; break; case "uaz": case "uaz_physics": type = "jeep"; break; case "bm21": case "bm21_drivable": case "bm21_troops": type = "truck"; break; default: type = "vehicle"; break; } if ( !IsDefined( level.uav_killstats[ type ] ) ) { level.uav_killstats[ type ] = 0; } self waittill( "death", attacker, cause ); if ( ( type == "helo" || type == "btr" ) || IsDefined( self.riders ) && self.riders.size > 0 ) { if ( IsDefined( attacker ) && attacker == player ) { level.uav_killstats[ type ]++; } } } ExitFromCamera_Missile( player, reasonIsPain ) { player.is_flying_missile = undefined; text_TitleDestroy(); DrawTargetsEnd(); if ( IsDefined( level.uav_is_destroyed ) ) thread staticEffect( .5 ); player ControlsUnlink(); player CameraUnlink(); maps\_load::thermal_EffectsOff(); player ThermalVisionOff(); player RemoteCameraSoundscapeOff(); player VisionSetThermalForPlayer( level.visionThermalDefault, 0 ); if ( IsDefined( level.uav ) ) { if ( is_specialop() ) { level.uav ShowOnClient( self ); } else { level.uav Show(); } } if ( reasonIsPain ) { //fast switch back - go right to weapon, no flash player VisionSetNakedForPlayer( level.VISION_BLACK, 0 ); wait 0.05; player VisionSetNakedForPlayer( level.lvl_visionset, 0.4 ); player EnableWeapons(); player FreezeControls( false ); player ShowViewModel(); wait 0.2; HudItemsShow(); player EnableOffhandWeapons(); } else { //slow switch back - flash from missile explosion player VisionSetNakedForPlayer( "coup_sunblind", 0 ); player FreezeControls( true ); wait 0.05; player VisionSetNakedForPlayer( level.lvl_visionset, 1.0 ); player EnableWeapons(); player ShowViewModel(); wait 0.5; HudItemsShow(); player EnableOffhandWeapons(); player FreezeControls( false ); } player.is_controlling_UAV = undefined; level.uavTargetEnt = undefined; } ExitFromCamera_UAV( player, reasonIsPain ) { DrawTargetsEnd(); text_TitleFadeout(); text_NoticeFadeout(); player VisionSetNakedForPlayer( level.VISION_BLACK, 0.25 ); player VisionSetThermalForPlayer( level.VISION_BLACK, 0.25 ); if ( IsDefined( level.uav_is_destroyed ) ) player thread staticEffect( .5 ); wait 0.15; wait 0.35; text_TitleDestroy(); text_NoticeDestroy(); player Unlink(); player VisionSetThermalForPlayer( level.visionThermalDefault, 0 ); maps\_load::thermal_EffectsOff(); player ThermalVisionOff(); if ( IsDefined( player.fov_is_altered ) ) SetSavedDvar( "cg_fov", 65 ); if ( IsDefined( level.uav ) ) { if ( is_specialop() ) { level.uav ShowOnClient( self ); } else { level.uav Show(); } } if ( reasonIsPain ) { //fast switch back - go right to weapon player SwitchBackToMainWeaponFast(); player FreezeControls( true ); wait 0.15; player VisionSetNakedForPlayer( level.lvl_visionset, 0.4 ); player EnableWeapons(); player ShowViewModel(); wait 0.10; HudItemsShow(); player EnableOffhandWeapons(); player FreezeControls( false ); } else { //slow switch back - show laptop, etc player FreezeControls( true ); wait 0.05; player VisionSetNakedForPlayer( level.lvl_visionset, 0.75 ); player EnableWeapons(); player ShowViewModel(); wait 0.5; HudItemsShow(); player SwitchBackToMainWeapon(); player EnableOffhandWeapons(); player FreezeControls( false ); } player.is_controlling_UAV = undefined; level.uavTargetEnt = undefined; return; } WaitForAttackCommand( player ) { // I'd like to use GetCommandFromKey to make this "proper" incase of different keybindings // but it's not mp friendly... // dpad_left = GetCommandFromKey( "DPAD_LEFT" ); // dpad_left = GetCommandFromKey( "BUTTON_Y" ); // dpad_left = GetCommandFromKey( "BUTTON_B" ); // player NotifyOnPlayerCommand( "abort_remote_missile", "+actionslot 3" ); // DPad Left player NotifyOnPlayerCommand( "abort_remote_missile", "weapnext" ); // BUTTON_Y player NotifyOnPlayerCommand( "abort_remote_missile", "+stance" ); // BUTTON_B player NotifyOnPlayerCommand( "launch_remote_missile", "+attack" ); // BUTTON_RTRIG player thread wait_for_other(); player thread wait_for_command_thread( "abort_remote_missile", "abort" ); player thread wait_for_command_thread( "launch_remote_missile", "launch" ); player waittill( "remote_missile_attack", val ); if ( val == "launch" ) { return true; } else { return false; } } wait_for_command_thread( msg, val ) { self endon( "remote_missile_attack" ); self waittill( msg ); self notify( "remote_missile_attack", val ); } wait_for_other() { self endon( "remote_missile_attack" ); for ( ;; ) { wait( 0.05 ); if ( self.took_damage ) { break; } if ( !flag( "uav_enabled" ) ) { break; } if ( IsDefined( level.uav_is_destroyed ) ) { break; } } self notify( "remote_missile_attack", "abort" ); } HudItemsHide() { if ( level.players.size > 0 ) { for ( i = 0; i < level.players.size; i++ ) { if( isdefined( level.players[ i ].using_uav ) && level.players[ i ].using_uav ) setdvar( "ui_remotemissile_playernum", (i+1) ); // 0 = no uav, 1 = player1, 2 = player2 } } else { SetSavedDvar( "compass", "0" ); SetSavedDvar( "ammoCounterHide", "1" ); SetSavedDvar( "actionSlotsHide", "1" ); } } HudItemsShow() { if( level.players.size > 0 ) { setdvar( "ui_remotemissile_playernum", 0 ); // 0 = no uav, 1 = player1, 2 = player2 } else { SetSavedDvar( "compass", "1" ); SetSavedDvar( "ammoCounterHide", "0" ); SetSavedDvar( "actionSlotsHide", "0" ); } } FireMissileFromUAVPlayer( player ) { Earthquake( 0.4, 1, level.uavRig.origin, 5000 ); org = level.uavRig.origin; playerAngles = player GetPlayerAngles(); forward = AnglesToForward( playerAngles ); right = AnglesToRight( playerAngles ); start = org + ( right * 700.0 ) + ( forward * -300.0 ); end = start + forward * 10.0; if ( IsDefined( level.remote_missile_snow ) ) { missile = MagicBullet( "remote_missile_snow", start, end, player ); } else { if ( IsDefined( level.remote_missile_invasion ) ) missile = MagicBullet( "remote_missile_invasion", start, end, player ); else missile = MagicBullet( "remote_missile", start, end, player ); } thread NotifyOnMissileDeath( missile ); return missile; } setup_remote_missile_target() { if ( !isdefined( level.remote_missile_targets ) ) level.remote_missile_targets = []; level.remote_missile_targets[ level.remote_missile_targets.size ] = self; if ( IsDefined( level.player.draw_red_boxes ) && !isdefined( level.uav_is_destroyed ) ) self draw_target(); self waittill( "death" ); if ( !isdefined( self ) ) return; if ( IsDefined( self.has_target_shader ) ) { self.has_target_shader = undefined; Target_Remove( self ); } level.remote_missile_targets = array_remove( level.remote_missile_targets, self ); } DrawTargetsStart() { level.player.draw_red_boxes = true; level endon( "uav_destroyed" ); level endon( "draw_target_end" ); //level.player ThermalVisionFOFOverlayOn(); targets_per_frame = 4; targets_drawn = 0; time_between_updates = .05; if ( !isdefined( level.remote_missile_targets ) ) return; foreach ( tgt in level.remote_missile_targets ) { if ( IsAlive( tgt ) ) { tgt draw_target(); targets_drawn++; if ( targets_drawn >= targets_per_frame ) { targets_drawn = 0; wait time_between_updates; } } else { level.remote_missile_targets = array_remove( level.remote_missile_targets, tgt ); } } } draw_target() { self.has_target_shader = true; if ( IsDefined( self.helicopter_predator_target_shader ) ) { Target_Set( self, ( 0, 0, -96 ) ); } else { Target_Set( self, ( 0, 0, 64 ) ); } if ( IsAI( self ) ) { Target_SetShader( self, "remotemissile_infantry_target" ); } else if ( IsPlayer( self ) )// Make sure you add the player to the level.remote_missile_targets before use { Target_SetShader( self, "hud_fofbox_self_sp" ); } else { Target_SetShader( self, "veh_hud_target" ); } // There is an order of execution issue, which is why this is commented out. // If player 2 ( level.players[ 1 ] ) runs the Target_ShowToPlayer() last, then player 1 will be able // to see the targets. // So, the work around is to figure out who is controlling the UAV, then call to Target_ShowToPlayer() // before Target_HideFromPlayer() // foreach( player in level.players ) // { // if( IsDefined( player.is_controlling_UAV ) && player.is_controlling_UAV ) // Target_ShowToPlayer( self, player ); // else // Target_HideFromPlayer( self, player ); // } uav_controller = undefined; non_uav_controller = undefined; foreach ( player in level.players ) { if ( IsDefined( player.is_controlling_UAV ) && player.is_controlling_UAV ) { uav_controller = player; } else { non_uav_controller = player; } } Target_ShowToPlayer( self, uav_controller ); if ( IsDefined( non_uav_controller ) ) { Target_HideFromPlayer( self, non_uav_controller ); } } DrawTargetsEnd() { level notify( "draw_target_end" ); //level.player ThermalVisionFOFOverlayOff(); waittillframeend;// was colliding with self waittill death which also removes the target level.player.draw_red_boxes = undefined; if ( IsDefined( level.remote_missile_targets ) ) { foreach ( tgt in level.remote_missile_targets ) { if ( !isdefined( tgt ) ) { level.remote_missile_targets = array_remove( level.remote_missile_targets, tgt ); } if ( IsDefined( tgt ) ) { if ( IsDefined( tgt.has_target_shader ) ) { tgt.has_target_shader = undefined; Target_Remove( tgt ); } } } } } SwitchBackToMainWeapon() { return SwitchBackToMainWeapon_internal( ::_switcher ); } SwitchBackToMainWeaponFast() { return SwitchBackToMainWeapon_internal( ::_switcherNow ); } _switcher( weapName ) { self SwitchToWeapon( weapName ); } _switcherNow( weapName ) { self SwitchToWeaponImmediate( weapName ); } SwitchBackToMainWeapon_internal( func ) { if ( self ent_flag_exist( "coop_downed" ) && self ent_flag( "coop_downed" ) ) { return; } //"primary", "offhand", "item", "altmode", and "exclusive". weapons = self GetWeaponsList( "primary", "altmode" ); foreach ( weapon in weapons ) { if ( self.last_weapon == weapon ) { self [[ func ]]( self.last_weapon ); return; } } if ( weapons.size > 0 ) self [[ func ]]( weapons[ 0 ] ); } staticEffect( duration ) { org = Spawn( "script_origin", ( 0, 0, 1 ) ); org.origin = self.origin; org PlaySound( "predator_drone_static", "sounddone" ); static = NewClientHudElem( self ); static.horzAlign = "fullscreen"; static.vertAlign = "fullscreen"; static SetShader( "ac130_overlay_grain", 640, 480 ); wait( duration ); static Destroy(); wait( 3 ); org StopSounds(); wait( 1 ); org Delete(); }