mirror of
https://github.com/reaaLx/nx1-gsc-dump.git
synced 2025-06-28 07:11:50 +00:00
Init
This commit is contained in:
1852
maps/mp/killstreaks/_ac130.gsc
Normal file
1852
maps/mp/killstreaks/_ac130.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1761
maps/mp/killstreaks/_airdrop.gsc
Normal file
1761
maps/mp/killstreaks/_airdrop.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1170
maps/mp/killstreaks/_airstrike.gsc
Normal file
1170
maps/mp/killstreaks/_airstrike.gsc
Normal file
File diff suppressed because it is too large
Load Diff
1301
maps/mp/killstreaks/_autosentry.gsc
Normal file
1301
maps/mp/killstreaks/_autosentry.gsc
Normal file
File diff suppressed because it is too large
Load Diff
211
maps/mp/killstreaks/_blueshell.gsc
Normal file
211
maps/mp/killstreaks/_blueshell.gsc
Normal file
@ -0,0 +1,211 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
|
||||
// Each Killstreak has its own initialization function. This Script has two main purposes.
|
||||
// (1). All global data and assets used by this killstreak should be initialized here.
|
||||
// (2). The callback that executes when a player activates this killstreak should be set here.
|
||||
// TODO: A call to this script must be added to the script init() in the file c:\trees\nx1\game\share\raw\maps\mp\killstreaks\_killstreaks.gsc,
|
||||
// this is were each individual killstreak is initialized.
|
||||
init()
|
||||
{
|
||||
//This is a good place to precache assets, load up fx, or setup any global data that might be needed, NOTE: Everything defined in killstreakTable.csv
|
||||
//will be precached automatically ( see initKillstreakData() in _killstreaks.gsc if interested ) so you do not need to worry about initializing the
|
||||
//strings/weapons/materials/sounds defined there. If, for example, you were going to manually script up a plane flyiing over when this killstreak was
|
||||
//activated you would want to precache that model here.
|
||||
|
||||
|
||||
//load the fx
|
||||
level._effect[ "blueshell" ] = loadfx( "nx/misc/prototype_saul" );
|
||||
|
||||
|
||||
//This is were the killstreak activation callback is set
|
||||
//TODO: Replace "killstreak_template" with the name of the new killstreak as defined in killstreakTable.csv
|
||||
//Most killstreaks use a try fuction ( which i recommend, even if it is not necessary for this particualr killstreak it is nice to have a consistent model )
|
||||
//the try script will make sure it is ok to fire the killstreak before the actual killstreak script is called.
|
||||
level._killstreakFuncs["blueshell"] = ::try_use_killstreak;
|
||||
|
||||
|
||||
//Use this script to update/initialize players as they connect to the game
|
||||
level thread onPlayerConnect();
|
||||
}
|
||||
|
||||
|
||||
// This script is running on the global level object, it monitors players connecting to the game.
|
||||
// Its main purpose is to apply the onPlayerSpawned script to each player as they connect to the game.
|
||||
onPlayerConnect()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
level waittill("connected", player);
|
||||
player thread onPlayerSpawned();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This script is running on each player in the game, it recieves a notification each time the player it is running on spawns in the game
|
||||
// Its main purpose is to initialize any per player data, as well as update the player subject to any global killstreak data when that player spawns.
|
||||
onPlayerSpawned()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
println( "player spwaned" );
|
||||
|
||||
// init/manage any per player killstreak data here
|
||||
}
|
||||
}
|
||||
|
||||
//Many of the killstreaks have a try block that will test level conditions to make sure it is ok to fire the killstreak now. A good example of this is for the air killstreaks.
|
||||
//Only a certain number of vehicles are allowed in the air at any given time, so if the airspace is full and the killstreak cannot be fired this try should return false.
|
||||
//If there are any preconditions that must be met in order to fire this killstreak they should be checked in this script.
|
||||
//NOTE: If this script returns true the killstreak system will consider this killstreak usage complete and the dpad icon will be removed, if this script returns false nothing will
|
||||
//change and the system will just continue to wait for the the player to activate the killstreak by pressing right on the dpad.
|
||||
try_use_killstreak( lifeId )
|
||||
{
|
||||
is_ok_to_use_killstreak = true;
|
||||
|
||||
if( is_ok_to_use_killstreak )
|
||||
{
|
||||
if( killstreak_template_use( lifeId ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// This is the callback that executes when the killstreak is activated by a player pressing on the dpad. This is called from the script killstreakUsePressed()
|
||||
// located in the file _killstreaks.gsc
|
||||
killstreak_template_use( lifeId )
|
||||
{
|
||||
assert( isDefined( self ) );
|
||||
println( "Killstreak Template Fired!!" );
|
||||
|
||||
player = self getHighestKillstreakPlayerNotOnMyTeam();
|
||||
|
||||
//if we couldnt find a target bail out.
|
||||
if( !isDefined( player ))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
fxObj = player createFxObj();
|
||||
|
||||
wait( 0.10 ); //wait two server frames before playing fx
|
||||
|
||||
fxobj thread doTheFx();
|
||||
fxobj thread waitAndDelete( 10.0 );
|
||||
|
||||
wait( 1.6 );
|
||||
player playSound( "prototype_missile_incoming" );
|
||||
|
||||
// This works
|
||||
/*
|
||||
PlayFX( level._effect["blueshell"], player.origin );
|
||||
wait( 1.7 );
|
||||
player playSound( "prototype_missile_incoming" );
|
||||
*/
|
||||
|
||||
wait( 3.4 );
|
||||
RadiusDamage( fxobj.origin, 100, 300, 25, self );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
waitAndDelete( time )
|
||||
{
|
||||
wait( time );
|
||||
self delete();
|
||||
}
|
||||
|
||||
doTheFx()
|
||||
{
|
||||
PlayFXOnTagForClients( level._effect["blueshell"], self, "TAG_ORIGIN", level._players );
|
||||
}
|
||||
|
||||
createFxObj()
|
||||
{
|
||||
tag_origin = spawn( "script_model", self.origin );
|
||||
tag_origin setmodel( "tag_origin" );
|
||||
|
||||
//tag_origin hide();
|
||||
|
||||
if ( isdefined( self.origin ) )
|
||||
tag_origin.origin = self.origin;
|
||||
if ( isdefined( self.angles ) )
|
||||
tag_origin.angles = self.angles;
|
||||
|
||||
return tag_origin;
|
||||
}
|
||||
|
||||
getHighestKillstreakPlayerNotOnMyTeam()
|
||||
{
|
||||
team = self.pers["team"];
|
||||
curr_highest_killstreak = -1;
|
||||
curr_player = undefined;
|
||||
|
||||
//TagZP<TODO> add los checks from above to make sure the player is outside.
|
||||
|
||||
//possibly return a list of random targets for fun.
|
||||
|
||||
//possibly use player score insted of killstreak to select a target.
|
||||
|
||||
//this implies that we are in a team based game mode such as TDM or DOM
|
||||
if( level._teamBased )
|
||||
{
|
||||
foreach( player in level._players )
|
||||
{
|
||||
//if the player is not on my team check if they have the highest killstreak!!!!!
|
||||
if( player.pers["team"] != team )
|
||||
{
|
||||
if( player.pers["cur_kill_streak"] > curr_highest_killstreak )
|
||||
{
|
||||
curr_highest_killstreak = player.pers["cur_kill_streak"];
|
||||
curr_player = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//If we are not in a team based game we must be in a FFA game
|
||||
foreach( player in level._players )
|
||||
{
|
||||
//if the player is not on my team kill them!!!!!
|
||||
if( player != self )
|
||||
{
|
||||
if( player.pers["cur_kill_streak"] > curr_highest_killstreak )
|
||||
{
|
||||
curr_highest_killstreak = player.pers["cur_kill_streak"];
|
||||
curr_player = player;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert( isDefined( curr_player ));
|
||||
return curr_player;
|
||||
}
|
||||
|
||||
|
||||
// A helper script that will kill a player. Used by the example killstreak.
|
||||
killPlayer( player )
|
||||
{
|
||||
player thread [[level._callbackPlayerDamage]](
|
||||
self, // eInflictor The entity that causes the damage.(e.g. a turret)
|
||||
self, // eAttacker The entity that is attacking.
|
||||
500, // iDamage Integer specifying the amount of damage done
|
||||
0, // iDFlags Integer specifying flags that are to be applied to the damage
|
||||
"MOD_SUICIDE", // sMeansOfDeath Integer specifying the method of death MOD_RIFLE_BULLET
|
||||
player.primaryweapon, // sWeapon The weapon number of the weapon used to inflict the damage
|
||||
player.origin, // vPoint The point the damage is from?
|
||||
(0, 0, 0), // vDir The direction of the damage
|
||||
"none", // sHitLoc The location of the hit
|
||||
0 // psOffsetTime The time offset for the damage
|
||||
);
|
||||
}
|
414
maps/mp/killstreaks/_emp.gsc
Normal file
414
maps/mp/killstreaks/_emp.gsc
Normal file
@ -0,0 +1,414 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
|
||||
init()
|
||||
{
|
||||
level._effect[ "emp_flash" ] = loadfx( "explosions/emp_flash_mp" );
|
||||
|
||||
level._teamEMPed["allies"] = false;
|
||||
level._teamEMPed["axis"] = false;
|
||||
|
||||
if( level._multiTeamBased )
|
||||
{
|
||||
for( i = 0; i < level._teamNameList.size; i++ )
|
||||
{
|
||||
level._teamEMPed[level._teamNameList[i]] = false;
|
||||
}
|
||||
|
||||
}
|
||||
level._empPlayer = undefined;
|
||||
|
||||
if ( level._teamBased )
|
||||
level thread EMP_TeamTracker();
|
||||
else
|
||||
level thread EMP_PlayerTracker();
|
||||
|
||||
level._killstreakFuncs["emp"] = ::EMP_Use;
|
||||
|
||||
level thread onPlayerConnect();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
onPlayerConnect()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
level waittill("connected", player);
|
||||
player thread onPlayerSpawned();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onPlayerSpawned()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
|
||||
if ( (level._teamBased && level._teamEMPed[self.team]) || (!level._teamBased && isDefined( level._empPlayer ) && level._empPlayer != self) )
|
||||
self setEMPJammed( true );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EMP_Use( lifeId, delay )
|
||||
{
|
||||
assert( isDefined( self ) );
|
||||
|
||||
if ( !isDefined( delay ) )
|
||||
delay = 5.0;
|
||||
|
||||
myTeam = self.pers["team"];
|
||||
|
||||
if ( level._teamBased )
|
||||
self thread EMP_JamTeams( myTeam, 60.0, delay );
|
||||
else
|
||||
self thread EMP_JamPlayers( self, 60.0, delay );
|
||||
|
||||
self maps\mp\_matchdata::logKillstreakEvent( "emp", self.origin );
|
||||
self notify( "used_emp" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
EMP_JamTeams( teamName, duration, delay )
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
thread teamPlayerCardSplash( "used_emp", self );
|
||||
|
||||
level notify ( "EMP_JamTeams" + teamName );
|
||||
level endon ( "EMP_JamTeams" + teamName );
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
player playLocalSound( "emp_activate" );
|
||||
|
||||
if ( player.team == teamName )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.gotEMPed = true;
|
||||
if ( player _hasPerk( "specialty_flakjacket" ))
|
||||
{
|
||||
player notify ( "disableTrophy" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( player _hasPerk( "specialty_localjammer" ) )
|
||||
player RadarJamOff();
|
||||
}
|
||||
|
||||
visionSetNaked( "coup_sunblind", 0.1 );
|
||||
thread empEffects();
|
||||
|
||||
wait ( 0.1 );
|
||||
|
||||
// resetting the vision set to the same thing won't normally have an effect.
|
||||
// however, if the client receives the previous visionset change in the same packet as this one,
|
||||
// this will force them to lerp from the bright one to the normal one.
|
||||
visionSetNaked( "coup_sunblind", 0 );
|
||||
visionSetNaked( getDvar( "mapname" ), 3.0 );
|
||||
|
||||
foreach( team in level._teamNameList )
|
||||
{
|
||||
if ( team != teamName )
|
||||
{
|
||||
level._teamEMPed[team] = true;
|
||||
}
|
||||
}
|
||||
|
||||
level notify ( "emp_update" );
|
||||
|
||||
level destroyActiveVehicles( self );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration );
|
||||
|
||||
foreach( team in level._teamNameList )
|
||||
{
|
||||
if ( team != teamName )
|
||||
{
|
||||
level._teamEMPed[team] = false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == teamName )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.gotEMPed = false;
|
||||
if ( (player _hasPerk( "specialty_flakjacket" )) && !(isDefined ( player.gotEMPGrenaded ) && player.gotEMPGrenaded == true))
|
||||
{
|
||||
player notify ( "enableTrophy" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( player _hasPerk( "specialty_localjammer" ) )
|
||||
player RadarJamOn();
|
||||
}
|
||||
level notify ( "emp_update" );
|
||||
level notify ( "enableTrophy" );
|
||||
}
|
||||
|
||||
EMPGrenade_JamPlayer( duration )
|
||||
{
|
||||
level endon ( "EMP_JamPlayers" );
|
||||
self endon ( "death" );
|
||||
self endon ( "disconnect" );
|
||||
|
||||
self playLocalSound( "emp_activate" );
|
||||
|
||||
if ( self _hasPerk( "specialty_localjammer" ) )
|
||||
self RadarJamOff();
|
||||
|
||||
self.gotEMPGrenaded = true;
|
||||
if (self _hasPerk( "specialty_flakjacket" ))
|
||||
{
|
||||
self notify ( "disableTrophy" );
|
||||
}
|
||||
|
||||
wait ( 0.1 );
|
||||
|
||||
self setEMPJammed( true );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration );
|
||||
|
||||
self setEMPJammed( false );
|
||||
|
||||
if ( self _hasPerk( "specialty_localjammer" ) )
|
||||
self RadarJamOn();
|
||||
|
||||
self.gotEMPGrenaded = false;
|
||||
if ( (self _hasPerk( "specialty_flakjacket" )) && !(isDefined ( self.gotEMPed ) && self.gotEMPed == true ))
|
||||
{
|
||||
self notify ( "enableTrophy" );
|
||||
}
|
||||
}
|
||||
|
||||
EMP_JamPlayers( owner, duration, delay )
|
||||
{
|
||||
level notify ( "EMP_JamPlayers" );
|
||||
level endon ( "EMP_JamPlayers" );
|
||||
|
||||
assert( isDefined( owner ) );
|
||||
|
||||
//wait ( delay );
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
player playLocalSound( "emp_activate" );
|
||||
|
||||
if ( player == owner )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.gotEMPed = true;
|
||||
if ( player _hasPerk( "specialty_flakjacket" ))
|
||||
{
|
||||
player notify ( "disableTrophy" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( player _hasPerk( "specialty_localjammer" ) )
|
||||
player RadarJamOff();
|
||||
}
|
||||
|
||||
visionSetNaked( "coup_sunblind", 0.1 );
|
||||
thread empEffects();
|
||||
|
||||
wait ( 0.1 );
|
||||
|
||||
// resetting the vision set to the same thing won't normally have an effect.
|
||||
// however, if the client receives the previous visionset change in the same packet as this one,
|
||||
// this will force them to lerp from the bright one to the normal one.
|
||||
visionSetNaked( "coup_sunblind", 0 );
|
||||
visionSetNaked( getDvar( "mapname" ), 3.0 );
|
||||
|
||||
level notify ( "emp_update" );
|
||||
|
||||
level._empPlayer = owner;
|
||||
level._empPlayer thread empPlayerFFADisconnect();
|
||||
level destroyActiveVehicles( owner );
|
||||
|
||||
level notify ( "emp_update" );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration );
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player == owner )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.gotEMPed = false;
|
||||
if ( (player _hasPerk( "specialty_flakjacket" )) && !(isDefined ( player.gotEMPGrenaded ) && player.gotEMPGrenaded == true))
|
||||
{
|
||||
player notify ( "enableTrophy" );
|
||||
}
|
||||
}
|
||||
|
||||
if ( player _hasPerk( "specialty_localjammer" ) )
|
||||
player RadarJamOn();
|
||||
}
|
||||
|
||||
level._empPlayer = undefined;
|
||||
level notify ( "emp_update" );
|
||||
level notify ( "emp_ended" );
|
||||
level notify ( "enableTrophy" );
|
||||
}
|
||||
|
||||
empPlayerFFADisconnect()
|
||||
{
|
||||
level endon ( "EMP_JamPlayers" );
|
||||
level endon ( "emp_ended" );
|
||||
|
||||
self waittill( "disconnect" );
|
||||
level notify ( "emp_update" );
|
||||
}
|
||||
|
||||
empEffects()
|
||||
{
|
||||
foreach( player in level._players )
|
||||
{
|
||||
playerForward = anglestoforward( player.angles );
|
||||
playerForward = ( playerForward[0], playerForward[1], 0 );
|
||||
playerForward = VectorNormalize( playerForward );
|
||||
|
||||
empDistance = 20000;
|
||||
|
||||
empEnt = Spawn( "script_model", player.origin + ( 0, 0, 8000 ) + Vector_Multiply( playerForward, empDistance ) );
|
||||
empEnt setModel( "tag_origin" );
|
||||
empEnt.angles = empEnt.angles + ( 270, 0, 0 );
|
||||
empEnt thread empEffect( player );
|
||||
}
|
||||
}
|
||||
|
||||
empEffect( player )
|
||||
{
|
||||
player endon( "disconnect" );
|
||||
|
||||
wait( 0.5 );
|
||||
PlayFXOnTagForClients( level._effect[ "emp_flash" ], self, "tag_origin", player );
|
||||
}
|
||||
|
||||
EMP_TeamTracker()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill_either ( "joined_team", "emp_update" );
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == "spectator" )
|
||||
continue;
|
||||
|
||||
player setEMPJammed( level._teamEMPed[player.team] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EMP_PlayerTracker()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill_either ( "joined_team", "emp_update" );
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == "spectator" )
|
||||
continue;
|
||||
|
||||
if ( isDefined( level._empPlayer ) && level._empPlayer != player )
|
||||
player setEMPJammed( true );
|
||||
else
|
||||
player setEMPJammed( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destroyActiveVehicles( attacker )
|
||||
{
|
||||
if ( isDefined( attacker ) )
|
||||
{
|
||||
foreach ( heli in level._helis )
|
||||
radiusDamage( heli.origin, 384, 5000, 5000, attacker );
|
||||
|
||||
foreach ( littleBird in level._littleBird )
|
||||
radiusDamage( littleBird.origin, 384, 5000, 5000, attacker );
|
||||
|
||||
foreach ( turret in level._turrets )
|
||||
radiusDamage( turret.origin, 2, 5000, 5000, attacker );
|
||||
|
||||
foreach ( rocket in level._rockets )
|
||||
rocket notify ( "death" );
|
||||
|
||||
if ( level._teamBased )
|
||||
{
|
||||
foreach ( uav in level._uavModels["allies"] )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000, attacker );
|
||||
|
||||
foreach ( uav in level._uavModels["axis"] )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000, attacker );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( uav in level._uavModels )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000, attacker );
|
||||
}
|
||||
|
||||
if ( isDefined( level._ac130player ) )
|
||||
radiusDamage( level._ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000, attacker );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( heli in level._helis )
|
||||
radiusDamage( heli.origin, 384, 5000, 5000 );
|
||||
|
||||
foreach ( littleBird in level._littleBird )
|
||||
radiusDamage( littleBird.origin, 384, 5000, 5000 );
|
||||
|
||||
foreach ( turret in level._turrets )
|
||||
radiusDamage( turret.origin, 2, 5000, 5000 );
|
||||
|
||||
foreach ( rocket in level._rockets )
|
||||
rocket notify ( "death" );
|
||||
|
||||
if ( level._teamBased )
|
||||
{
|
||||
foreach ( uav in level._uavModels["allies"] )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000 );
|
||||
|
||||
foreach ( uav in level._uavModels["axis"] )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000 );
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( uav in level._uavModels )
|
||||
radiusDamage( uav.origin, 384, 5000, 5000 );
|
||||
}
|
||||
|
||||
if ( isDefined( level._ac130player ) )
|
||||
radiusDamage( level._ac130.planeModel.origin+(0,0,10), 1000, 5000, 5000 );
|
||||
}
|
||||
}
|
229
maps/mp/killstreaks/_exosuit.gsc
Normal file
229
maps/mp/killstreaks/_exosuit.gsc
Normal file
@ -0,0 +1,229 @@
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
#include common_scripts\utility;
|
||||
|
||||
|
||||
EXOSUIT_CHANGE_TIME_SECONDS = 3.0;
|
||||
EXOSUIT_TABLE_FILE = "mp/exosuitTable.csv";
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
init()
|
||||
{
|
||||
precacheString( &"MPUI_CHANGING_SUIT" );
|
||||
PrecacheItem( "aresminigun_mp" );
|
||||
|
||||
level._killStreakFuncs[ "exosuit" ] = ::tryUseExosuit;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
tryUseExosuit( lifeId )
|
||||
{
|
||||
self thread chooseExosuit();
|
||||
|
||||
self waittill ( "suit_chosen" );
|
||||
|
||||
// suit perk will be set if the function above is successful
|
||||
if ( self _hasPerk( "specialty_stealthsuit" ) || self _hasPerk( "specialty_agisuit" ) ||
|
||||
self _hasPerk( "specialty_tacsuit" ) || self _hasPerk( "specialty_juggersuit" ) ||
|
||||
self _hasPerk( "specialty_jetsuit" ))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
chooseExosuit()
|
||||
{
|
||||
self endon ( "death" );
|
||||
self endon ( "disconnect" );
|
||||
level endon ( "game_ended" );
|
||||
|
||||
suitName = "specialty_juggersuit";
|
||||
|
||||
if ( self isUsingRemote() )
|
||||
{
|
||||
if ( self getCurrentWeapon() == "killstreak_uav_mp" )
|
||||
{
|
||||
self _disableWeaponSwitch();
|
||||
self _disableOffhandWeapons();
|
||||
self _disableUsability();
|
||||
self switchToWeapon( self getLastWeapon() );
|
||||
self waittill ( "weapon_change" );
|
||||
self _enableWeaponSwitch();
|
||||
self _enableOffhandWeapons();
|
||||
self _enableUsability();
|
||||
}
|
||||
|
||||
self notify ( "suit_chosen" );
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( suitName == "specialty_stealthsuit" || suitName == "specialty_agisuit" ||
|
||||
suitName == "specialty_tacsuit" || suitName == "specialty_juggersuit" ||
|
||||
suitName == "specialty_jetsuit" );
|
||||
self thread tryWearSuit( suitName );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
closeExosuitMenuOnDeath()
|
||||
{
|
||||
self endon ( "menuresponse" );
|
||||
self endon ( "disconnect" );
|
||||
level endon ( "game_ended" );
|
||||
|
||||
self waittill ( "death" );
|
||||
|
||||
self closePopupMenu();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
tryWearSuit( suitName )
|
||||
{
|
||||
self endon ( "death" );
|
||||
self endon ( "disconnect" );
|
||||
level endon ( "game_ended" );
|
||||
|
||||
// tagTMR<TODO>: Add playLocalSound and playTeamSound here
|
||||
|
||||
if ( self _hasPerk( "specialty_twoprimaries" ))
|
||||
{
|
||||
self thread maps\mp\gametypes\_class::cleanHULChud();
|
||||
self notify ( "disable_HULC" );
|
||||
}
|
||||
|
||||
self _disableWeapon();
|
||||
self _disableOffhandWeapons();
|
||||
self _disableUsability();
|
||||
|
||||
|
||||
// Don't want overpowered combinations so no perks will coexist with suits for now
|
||||
self _clearPerks();
|
||||
maps\mp\perks\_perks::givePerk( suitName );
|
||||
|
||||
self _enableWeapon();
|
||||
self _enableOffhandWeapons();
|
||||
self _enableUsability();
|
||||
|
||||
// tagSS<NOTE>: No attempt is made to save the previous model. This would be needed if the suit was able to be removed
|
||||
// before dying, in order to restore the proper randomized character. Note that this also sets the model.
|
||||
self detachAll();
|
||||
self giveSuitWeapons( suitName );
|
||||
|
||||
// tagTMR<NOTE>: The detatchAll() above will remove the flag carried, reattached if the player's spoda have one
|
||||
if ( isDefined( self.carryFlag ))
|
||||
{
|
||||
self attach( self.carryFlag, "J_spine4", true );
|
||||
}
|
||||
|
||||
waitframe();
|
||||
self notify ( "suit_chosen" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
exosuitUseBar()
|
||||
{
|
||||
self endon ( "disconnect" );
|
||||
|
||||
useBar = createPrimaryProgressBar( 25 );
|
||||
useBarText = createPrimaryProgressBarText( 25 );
|
||||
useBarText setText( &"MPUI_CHANGING_SUIT" );
|
||||
|
||||
useBar updateBar( 0, 1 / EXOSUIT_CHANGE_TIME_SECONDS );
|
||||
for ( waitedTime = 0; waitedTime < EXOSUIT_CHANGE_TIME_SECONDS && isAlive( self ) && !level._gameEnded; waitedTime += 0.05 )
|
||||
{
|
||||
wait ( 0.05 );
|
||||
}
|
||||
|
||||
useBar destroyElem();
|
||||
useBarText destroyElem();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
giveSuitWeapons( suitName )
|
||||
{
|
||||
primaryWeapon = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 2 );
|
||||
primaryAttachment = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 3 );
|
||||
primaryAttachment2 = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 4 );
|
||||
secondaryWeapon = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 5 );
|
||||
secondaryAttachment = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 6 );
|
||||
secondaryAttachment2 = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 7 );
|
||||
equipment = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 8 );
|
||||
loadoutOffhand = tablelookup( EXOSUIT_TABLE_FILE, 1, suitName, 9 );
|
||||
|
||||
// tagTMR<NOTE>: if there is no primary weapon, this suit will not have a weapon loadout to sub
|
||||
if (primaryWeapon != "none")
|
||||
{
|
||||
self takeAllWeapons();
|
||||
|
||||
self.loadoutPrimary = primaryWeapon;
|
||||
self.loadoutSecondary = secondaryWeapon;
|
||||
|
||||
primaryName = maps\mp\gametypes\_class::buildWeaponName( primaryWeapon, primaryAttachment, primaryAttachment2 );
|
||||
self _giveWeapon( primaryName, self.loadoutPrimaryCamo );
|
||||
self SwitchToWeapon ( primaryWeapon + "_mp" );
|
||||
|
||||
secondaryName = maps\mp\gametypes\_class::buildWeaponName( secondaryWeapon, secondaryAttachment, secondaryAttachment2 );
|
||||
self _giveWeapon( secondaryName, self.loadoutSecondaryCamo );
|
||||
|
||||
self SetOffhandPrimaryClass( "other" );
|
||||
|
||||
equipment = maps\mp\perks\_perks::validatePerk( 1, equipment );
|
||||
self maps\mp\perks\_perks::givePerk( equipment );
|
||||
|
||||
// Secondary Offhand
|
||||
offhandSecondaryWeapon = loadoutOffhand + "_mp";
|
||||
if ( loadoutOffhand == "flash_grenade" )
|
||||
self SetOffhandSecondaryClass( "flash" );
|
||||
else
|
||||
self SetOffhandSecondaryClass( "smoke" );
|
||||
|
||||
self giveWeapon( offhandSecondaryWeapon );
|
||||
if( loadOutOffhand == "smoke_grenade" )
|
||||
self setWeaponAmmoClip( offhandSecondaryWeapon, 1 );
|
||||
else if( loadOutOffhand == "flash_grenade" )
|
||||
self setWeaponAmmoClip( offhandSecondaryWeapon, 2 );
|
||||
else if( loadOutOffhand == "concussion_grenade" )
|
||||
self setWeaponAmmoClip( offhandSecondaryWeapon, 2 );
|
||||
else
|
||||
self setWeaponAmmoClip( offhandSecondaryWeapon, 1 );
|
||||
|
||||
self.primaryWeapon = primaryName;
|
||||
self.secondaryWeapon = secondaryName;
|
||||
|
||||
primaryTokens = strtok( primaryName, "_" );
|
||||
self.pers["primaryWeapon"] = primaryTokens[0];
|
||||
|
||||
self.isSniper = (weaponClass( self.primaryWeapon ) == "sniper");
|
||||
}
|
||||
|
||||
self maps\mp\gametypes\_teams::playerModelForWeapon( self.pers["primaryWeapon"], getBaseWeaponName( self.secondaryWeapon ) );
|
||||
self maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" );
|
||||
}
|
1155
maps/mp/killstreaks/_harrier.gsc
Normal file
1155
maps/mp/killstreaks/_harrier.gsc
Normal file
File diff suppressed because it is too large
Load Diff
2231
maps/mp/killstreaks/_helicopter.gsc
Normal file
2231
maps/mp/killstreaks/_helicopter.gsc
Normal file
File diff suppressed because it is too large
Load Diff
440
maps/mp/killstreaks/_jet.gsc
Normal file
440
maps/mp/killstreaks/_jet.gsc
Normal file
@ -0,0 +1,440 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
JET_MISSILE_DIRECTION = ( 1.0, 1.0, 20.0 );
|
||||
|
||||
// Each Killstreak has its own initialization function. This Script has two main purposes.
|
||||
// (1). All global data and assets used by this killstreak should be initialized here.
|
||||
// (2). The callback that executes when a player activates this killstreak should be set here.
|
||||
// TODO: A call to this script must be added to the script init() in the file c:\trees\nx1\game\share\raw\maps\mp\killstreaks\_killstreaks.gsc,
|
||||
// this is were each individual killstreak is initialized.
|
||||
init()
|
||||
{
|
||||
//precacheItem( "f50_remote_mp" );
|
||||
precacheModel( "vehicle_f50" );
|
||||
PrecacheMiniMapIcon( "compass_objpoint_airstrike_friendly" );
|
||||
PrecacheMiniMapIcon( "compass_objpoint_airstrike_busy" );
|
||||
PrecacheMiniMapIcon( "compass_objpoint_b2_airstrike_friendly" );
|
||||
|
||||
PrecacheMiniMapIcon( "compass_objpoint_b2_airstrike_enemy" );
|
||||
|
||||
|
||||
level._killStreakFuncs["jet"] = ::tryUseJet;
|
||||
|
||||
level._onfirefx = loadfx ("fire/fire_smoke_trail_L");
|
||||
level._fx_airstrike_afterburner = loadfx ("fire/jet_afterburner");
|
||||
level._fx_airstrike_contrail = loadfx ("smoke/jet_contrail");
|
||||
level._planes = 0;
|
||||
level._rockets = [];
|
||||
|
||||
}
|
||||
|
||||
tryUseJet( lifeId )
|
||||
{
|
||||
println( "tryuseJet" );
|
||||
if ( isDefined( level._civilianJetFlyBy ) )
|
||||
{
|
||||
self iPrintLnBold( &"MP_CIVILIAN_AIR_TRAFFIC" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( self isUsingRemote() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
result = self selectJetLocation( lifeId );
|
||||
|
||||
if ( !isDefined( result ) || !result )
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
selectJetLocation( lifeId )
|
||||
{
|
||||
println( "SelectJetLocation" );
|
||||
chooseDirection = true;
|
||||
|
||||
targetSize = level._mapSize / 5.625; // 138 in 720
|
||||
if ( level._splitscreen )
|
||||
targetSize *= 1.5;
|
||||
|
||||
self beginLocationSelection( "map_artillery_selector", chooseDirection, false, targetSize );
|
||||
self.selectingLocation = true;
|
||||
|
||||
self setblurforplayer( 4.0, 0.3 );
|
||||
self thread waitForJetCancel();
|
||||
|
||||
self thread endJetSelectionOn( "cancel_location" );
|
||||
self thread endJetSelectionOn( "death" );
|
||||
self thread endJetSelectionOn( "disconnect" );
|
||||
self thread endJetSelectionOn( "used" ); // so that this thread doesn't kill itself when we use an airstrike
|
||||
self thread endJetSelectionOnGameEnd();
|
||||
self thread endJetSelectionOnEMP();
|
||||
|
||||
self endon( "stop_location_selection" );
|
||||
|
||||
// wait for the selection. randomize the yaw if we're not doing a precision airstrike.
|
||||
self waittill( "confirm_location", location, directionYaw );
|
||||
|
||||
self setblurforplayer( 0, 0.3 );
|
||||
|
||||
self thread finishJetUsage( lifeId, location, directionYaw );
|
||||
return true;
|
||||
}
|
||||
|
||||
finishJetUsage( lifeId, location, directionYaw )
|
||||
{
|
||||
println( "finishJetUsage" );
|
||||
self notify( "used" );
|
||||
|
||||
// find underside of top of skybox
|
||||
trace = bullettrace( level._mapCenter + (0,0,1000000), level._mapCenter, false, undefined );
|
||||
location = (location[0], location[1], trace["position"][2] - 514);
|
||||
|
||||
self thread doJetAirStrike( lifeId, location, directionYaw, self, self.pers["team"] );
|
||||
}
|
||||
|
||||
|
||||
doJetAirStrike( lifeId, origin, yaw, owner, team )
|
||||
{
|
||||
println( "doJetAirStrike" );
|
||||
assert( isDefined( origin ) );
|
||||
assert( isDefined( yaw ) );
|
||||
|
||||
if ( isDefined( level._airstrikeInProgress ) )
|
||||
{
|
||||
while ( isDefined( level._airstrikeInProgress ) )
|
||||
level waittill ( "begin_airstrike" );
|
||||
|
||||
level._airstrikeInProgress = true;
|
||||
wait ( 2.0 );
|
||||
}
|
||||
|
||||
if ( !isDefined( owner ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
level._airstrikeInProgress = true;
|
||||
|
||||
num = 17 + randomint(3);
|
||||
trace = bullettrace(origin, origin + (0,0,-1000000), false, undefined);
|
||||
targetpos = trace["position"];
|
||||
|
||||
if ( level._teambased )
|
||||
{
|
||||
players = level._players;
|
||||
|
||||
for ( i = 0; i < level._players.size; i++ )
|
||||
{
|
||||
player = level._players[i];
|
||||
playerteam = player.pers["team"];
|
||||
if ( isdefined( playerteam ) )
|
||||
{
|
||||
player iprintln( &"MP_WAR_AIRSTRIKE_INBOUND", owner );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self callJetStrike( lifeId, owner, targetpos, yaw );
|
||||
|
||||
|
||||
wait( 1.0 );
|
||||
level._airstrikeInProgress = undefined;
|
||||
owner notify ( "begin_airstrike" );
|
||||
level notify ( "begin_airstrike" );
|
||||
|
||||
wait 7.5;
|
||||
|
||||
found = false;
|
||||
|
||||
}
|
||||
|
||||
callJetStrike( lifeId, owner, coord, yaw )
|
||||
{
|
||||
println( "calljetstrike" );
|
||||
heightEnt = undefined;
|
||||
// Get starting and ending point for the plane
|
||||
direction = ( 0, yaw, 0 );
|
||||
heightEnt = GetEnt( "airstrikeheight", "targetname" );
|
||||
|
||||
thread teamPlayerCardSplash( "used_stealth_airstrike", owner, owner.team );
|
||||
|
||||
planeHalfDistance = 12000;
|
||||
planeFlySpeed = 2000;
|
||||
|
||||
if ( !isDefined( heightEnt ) )//old system
|
||||
{
|
||||
println( "NO DEFINED AIRSTRIKE HEIGHT SCRIPT_ORIGIN IN LEVEL" );
|
||||
planeFlyHeight = 2000;
|
||||
if ( isdefined( level._airstrikeHeightScale ) )
|
||||
{
|
||||
planeFlyHeight *= level._airstrikeHeightScale;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
planeFlyHeight = heightEnt.origin[2];
|
||||
}
|
||||
|
||||
startPoint = coord + vector_multiply( anglestoforward( direction ), -1 * planeHalfDistance );
|
||||
|
||||
if ( isDefined( heightEnt ) )// used in the new height system
|
||||
startPoint *= (1,1,0);
|
||||
|
||||
startPoint += ( 0, 0, planeFlyHeight );
|
||||
|
||||
|
||||
endPoint = coord + vector_multiply( anglestoforward( direction ), planeHalfDistance*4 );
|
||||
|
||||
if ( isDefined( heightEnt ) )// used in the new height system
|
||||
endPoint *= (1,1,0);
|
||||
|
||||
endPoint += ( 0, 0, planeFlyHeight );
|
||||
|
||||
// Make the plane fly by
|
||||
d = length( startPoint - endPoint );
|
||||
flyTime = ( d / planeFlySpeed );
|
||||
owner endon("disconnect");
|
||||
|
||||
requiredDeathCount = lifeId;
|
||||
|
||||
self doJetStrike( lifeId, owner, startPoint+(0,0,randomInt(1000)), endPoint+(0,0,randomInt(1000)), flyTime, direction );
|
||||
|
||||
}
|
||||
|
||||
endJetSelectionOn( waitfor )
|
||||
{
|
||||
self endon( "stop_location_selection" );
|
||||
self waittill( waitfor );
|
||||
self thread stopJetLocationSelection( (waitfor == "disconnect") );
|
||||
}
|
||||
|
||||
endJetSelectionOnGameEnd()
|
||||
{
|
||||
self endon( "stop_location_selection" );
|
||||
level waittill( "game_ended" );
|
||||
self thread stopJetLocationSelection( false );
|
||||
}
|
||||
|
||||
endJetSelectionOnEMP()
|
||||
{
|
||||
self endon( "stop_location_selection" );
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill( "emp_update" );
|
||||
|
||||
if ( !self isEMPed() )
|
||||
continue;
|
||||
|
||||
self thread stopJetLocationSelection( false );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
doJetStrike( lifeId, owner, startPoint, endPoint, flyTime, direction )
|
||||
{
|
||||
self notifyOnPlayerCommand( "trigger_pulled", "+attack" );
|
||||
// plane spawning randomness = up to 125 units, biased towards 0
|
||||
// radius of bomb damage is 512
|
||||
println( "doJetStrike" );
|
||||
if ( !isDefined( owner ) )
|
||||
return;
|
||||
|
||||
startPathRandomness = 100;
|
||||
endPathRandomness = 150;
|
||||
|
||||
pathStart = startPoint + ( (randomfloat(2) - 1)*startPathRandomness, (randomfloat(2) - 1)*startPathRandomness, 0 );
|
||||
pathEnd = endPoint + ( (randomfloat(2) - 1)*endPathRandomness , (randomfloat(2) - 1)*endPathRandomness , 0 );
|
||||
|
||||
// Spawn the planes
|
||||
plane = spawnplane( owner, "script_model", pathStart, "compass_objpoint_b2_airstrike_friendly", "compass_objpoint_b2_airstrike_enemy" );
|
||||
|
||||
plane playLoopSound( "veh_b2_dist_loop" );
|
||||
plane setModel( "vehicle_f50" );
|
||||
plane thread handleJetEMP( owner );
|
||||
plane.lifeId = lifeId;
|
||||
|
||||
plane.angles = direction;
|
||||
forward = anglesToForward( direction );
|
||||
plane thread playJetPlaneFx();
|
||||
|
||||
//self HideHud();
|
||||
|
||||
//self VisionSetMissilecamForPlayer( game["thermal_vision"], 1.0 );
|
||||
self PlayerLinkWeaponviewToDelta( plane, "tag_player", 1.0, 45, 45, 0, 45, false );
|
||||
//self CameraLinkTo( plane, "tag_player" );
|
||||
|
||||
//self ThermalVisionOn();
|
||||
//self ThermalVisionFOFOverlayOn();
|
||||
|
||||
self _giveWeapon("heli_remote_mp");
|
||||
self SwitchToWeapon( "heli_remote_mp" );
|
||||
self DisableWeaponSwitch();
|
||||
self _disableOffhandWeapons();
|
||||
|
||||
plane moveTo( pathEnd, flyTime, 0, 0 );
|
||||
|
||||
println ("Before loop");
|
||||
|
||||
plane thread jetTimeout( flyTime );
|
||||
|
||||
self waittill ("trigger_pulled");
|
||||
|
||||
println ("Fired Gun" );
|
||||
origin = self GetEye();
|
||||
forward = AnglesToForward( self GetPlayerAngles() );
|
||||
endpoint = origin + forward;
|
||||
println ( "origin :" + origin );
|
||||
println ( "endpoint :" + endpoint );
|
||||
println ( "forward :" + forward );
|
||||
|
||||
|
||||
//bomb = spawnbomb( plane.origin, plane.angles );
|
||||
//bomb moveGravity( vector_multiply( anglestoforward( plane.angles ), 7000/1.5 ), 3.0 );
|
||||
|
||||
rocket = MagicBullet( "remotemissile_projectile_mp", origin, endpoint, owner );
|
||||
|
||||
rocket thread JetMissilehandleDamage();
|
||||
self unlink();
|
||||
self CameraLinkTo( rocket, "tag_origin" );
|
||||
self ControlsLinkTo( rocket );
|
||||
//self ThermalVisionFOFOverlayOff();
|
||||
rocket thread JetRocket_CleanupOnDeath();
|
||||
|
||||
|
||||
rocket waittill( "death" );
|
||||
self thread staticEffect( 0.5 );
|
||||
self ControlsUnlink();
|
||||
self CameraUnlink();
|
||||
|
||||
self thread Weapon_Return ();
|
||||
|
||||
println ("done with loop");
|
||||
}
|
||||
|
||||
jetTimeout( flyTime )
|
||||
{
|
||||
// Delete the plane after its flyby
|
||||
wait ( flyTime / 2.3 );
|
||||
self notify( "delete" );
|
||||
self delete();
|
||||
}
|
||||
|
||||
waitForJetCancel()
|
||||
{
|
||||
self waittill( "cancel_location" );
|
||||
self setblurforplayer( 0, 0.3 );
|
||||
}
|
||||
|
||||
stopJetLocationSelection( disconnected )
|
||||
{
|
||||
if ( !disconnected )
|
||||
{
|
||||
self setblurforplayer( 0, 0.3 );
|
||||
self endLocationSelection();
|
||||
self.selectingLocation = undefined;
|
||||
}
|
||||
self notify( "stop_location_selection" );
|
||||
}
|
||||
|
||||
useJet( lifeId, pos, yaw )
|
||||
{
|
||||
}
|
||||
|
||||
handleJetEMP( owner )
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
if ( owner isEMPed() )
|
||||
{
|
||||
playFxOnTag( level._onfirefx, self, "tag_engine_right" );
|
||||
playFxOnTag( level._onfirefx, self, "tag_engine_left" );
|
||||
return;
|
||||
}
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill ( "emp_update" );
|
||||
|
||||
if ( !owner isEMPed() )
|
||||
continue;
|
||||
|
||||
playFxOnTag( level._onfirefx, self, "tag_engine_right" );
|
||||
playFxOnTag( level._onfirefx, self, "tag_engine_left" );
|
||||
}
|
||||
}
|
||||
|
||||
JetRocket_CleanupOnDeath()
|
||||
{
|
||||
entityNumber = self getEntityNumber();
|
||||
level._rockets[ entityNumber ] = self;
|
||||
self waittill( "death" );
|
||||
|
||||
level._rockets[ entityNumber ] = undefined;
|
||||
}
|
||||
|
||||
Weapon_Return()
|
||||
{
|
||||
//self showhud;
|
||||
self takeWeapon( "heli_remote_mp" );
|
||||
self enableWeaponSwitch();
|
||||
self switchToWeapon( self getLastWeapon() );
|
||||
self _enableOffhandWeapons();
|
||||
}
|
||||
|
||||
|
||||
JetMissilehandleDamage()
|
||||
{
|
||||
self endon ( "death" );
|
||||
self endon ( "deleted" );
|
||||
|
||||
self setCanDamage( true );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "damage" );
|
||||
|
||||
println ( "projectile damaged!" );
|
||||
}
|
||||
}
|
||||
|
||||
playJetPlaneFx()
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
wait( 0.5);
|
||||
playfxontag( level._fx_airstrike_afterburner, self, "tag_engine_right" );
|
||||
wait( 0.5);
|
||||
playfxontag( level._fx_airstrike_afterburner, self, "tag_engine_left" );
|
||||
wait( 0.5);
|
||||
playfxontag( level._fx_airstrike_contrail, self, "tag_right_wingtip" );
|
||||
wait( 0.5);
|
||||
playfxontag( level._fx_airstrike_contrail, self, "tag_left_wingtip" );
|
||||
}
|
||||
|
||||
staticEffect( duration )
|
||||
{
|
||||
self endon ( "disconnect" );
|
||||
|
||||
staticBG = newClientHudElem( self );
|
||||
staticBG.horzAlign = "fullscreen";
|
||||
staticBG.vertAlign = "fullscreen";
|
||||
staticBG setShader( "white", 640, 480 );
|
||||
staticBG.archive = true;
|
||||
staticBG.sort = 10;
|
||||
|
||||
static = newClientHudElem( self );
|
||||
static.horzAlign = "fullscreen";
|
||||
static.vertAlign = "fullscreen";
|
||||
static setShader( "ac130_overlay_grain", 640, 480 );
|
||||
static.archive = true;
|
||||
static.sort = 20;
|
||||
|
||||
wait ( duration );
|
||||
|
||||
static destroy();
|
||||
staticBG destroy();
|
||||
}
|
1167
maps/mp/killstreaks/_killstreaks.gsc
Normal file
1167
maps/mp/killstreaks/_killstreaks.gsc
Normal file
File diff suppressed because it is too large
Load Diff
2124
maps/mp/killstreaks/_lockseekdie.gsc
Normal file
2124
maps/mp/killstreaks/_lockseekdie.gsc
Normal file
File diff suppressed because it is too large
Load Diff
316
maps/mp/killstreaks/_nuke.gsc
Normal file
316
maps/mp/killstreaks/_nuke.gsc
Normal file
@ -0,0 +1,316 @@
|
||||
#include common_scripts\utility;
|
||||
#include maps\mp\_utility;
|
||||
|
||||
init()
|
||||
{
|
||||
precacheItem( "nuke_mp" );
|
||||
precacheLocationSelector( "map_nuke_selector" );
|
||||
precacheString( &"MP_TACTICAL_NUKE_CALLED" );
|
||||
precacheString( &"MP_FRIENDLY_TACTICAL_NUKE" );
|
||||
precacheString( &"MP_TACTICAL_NUKE" );
|
||||
|
||||
level._effect[ "nuke_player" ] = loadfx( "explosions/player_death_nuke" );
|
||||
level._effect[ "nuke_flash" ] = loadfx( "explosions/player_death_nuke_flash" );
|
||||
level._effect[ "nuke_aftermath" ] = loadfx( "dust/nuke_aftermath_mp" );
|
||||
|
||||
game["strings"]["nuclear_strike"] = &"MP_TACTICAL_NUKE";
|
||||
|
||||
level._killstreakFuncs["nuke"] = ::tryUseNuke;
|
||||
|
||||
setDvarIfUninitialized( "scr_nukeTimer", 10 );
|
||||
setDvarIfUninitialized( "scr_nukeCancelMode", 0 );
|
||||
|
||||
level._nukeTimer = getDvarInt( "scr_nukeTimer" );
|
||||
level._cancelMode = getDvarInt( "scr_nukeCancelMode" );
|
||||
|
||||
/#
|
||||
setDevDvarIfUninitialized( "scr_nukeDistance", 5000 );
|
||||
setDevDvarIfUninitialized( "scr_nukeEndsGame", true );
|
||||
setDevDvarIfUninitialized( "scr_nukeDebugPosition", false );
|
||||
#/
|
||||
}
|
||||
|
||||
tryUseNuke( lifeId, allowCancel )
|
||||
{
|
||||
if( isDefined( level._nukeIncoming ) )
|
||||
{
|
||||
self iPrintLnBold( &"MP_NUKE_ALREADY_INBOUND" );
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( self isUsingRemote() && ( !isDefined( level._gtnw ) || !level._gtnw ) )
|
||||
return false;
|
||||
|
||||
if ( !isDefined( allowCancel ) )
|
||||
allowCancel = true;
|
||||
|
||||
self thread doNuke( allowCancel );
|
||||
self notify( "used_nuke" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
delaythread_nuke( delay, func )
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
wait ( delay );
|
||||
|
||||
thread [[ func ]]();
|
||||
}
|
||||
|
||||
doNuke( allowCancel )
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
level._nukeInfo = spawnStruct();
|
||||
level._nukeInfo.player = self;
|
||||
level._nukeInfo.team = self.pers["team"];
|
||||
|
||||
level._nukeIncoming = true;
|
||||
|
||||
maps\mp\gametypes\_gamelogic::pauseTimer();
|
||||
level._timeLimitOverride = true;
|
||||
setGameEndTime( int( gettime() + (level._nukeTimer * 1000) ) );
|
||||
setDvar( "ui_bomb_timer", 4 ); // Nuke sets '4' to avoid briefcase icon showing
|
||||
|
||||
if ( level._teambased )
|
||||
{
|
||||
thread teamPlayerCardSplash( "used_nuke", self, self.team );
|
||||
/*
|
||||
players = level.players;
|
||||
|
||||
foreach( player in level.players )
|
||||
{
|
||||
playerteam = player.pers["team"];
|
||||
if ( isdefined( playerteam ) )
|
||||
{
|
||||
if ( playerteam == self.pers["team"] )
|
||||
player iprintln( &"MP_TACTICAL_NUKE_CALLED", self );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !level._hardcoreMode )
|
||||
self iprintlnbold(&"MP_FRIENDLY_TACTICAL_NUKE");
|
||||
}
|
||||
|
||||
level thread delaythread_nuke( (level._nukeTimer - 3.3), ::nukeSoundIncoming );
|
||||
level thread delaythread_nuke( level._nukeTimer, ::nukeSoundExplosion );
|
||||
level thread delaythread_nuke( level._nukeTimer, ::nukeSlowMo );
|
||||
level thread delaythread_nuke( level._nukeTimer, ::nukeEffects );
|
||||
level thread delaythread_nuke( (level._nukeTimer + 0.25), ::nukeVision );
|
||||
level thread delaythread_nuke( (level._nukeTimer + 1.5), ::nukeDeath );
|
||||
level thread delaythread_nuke( (level._nukeTimer + 1.5), ::nukeEarthquake );
|
||||
level thread nukeAftermathEffect();
|
||||
|
||||
if ( level._cancelMode && allowCancel )
|
||||
level thread cancelNukeOnDeath( self );
|
||||
|
||||
// leaks if lots of nukes are called due to endon above.
|
||||
clockObject = spawn( "script_origin", (0,0,0) );
|
||||
clockObject hide();
|
||||
|
||||
while ( !isDefined( level._nukeDetonated ) )
|
||||
{
|
||||
clockObject playSound( "ui_mp_nukebomb_timer" );
|
||||
wait( 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
cancelNukeOnDeath( player )
|
||||
{
|
||||
player waittill_any( "death", "disconnect" );
|
||||
|
||||
if ( isDefined( player ) && level._cancelMode == 2 )
|
||||
player thread maps\mp\killstreaks\_emp::EMP_Use( 0, 0 );
|
||||
|
||||
|
||||
maps\mp\gametypes\_gamelogic::resumeTimer();
|
||||
level._timeLimitOverride = false;
|
||||
|
||||
setDvar( "ui_bomb_timer", 0 ); // Nuke sets '4' to avoid briefcase icon showing
|
||||
|
||||
level notify ( "nuke_cancelled" );
|
||||
}
|
||||
|
||||
nukeSoundIncoming()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
foreach( player in level._players )
|
||||
player playlocalsound( "nuke_incoming" );
|
||||
}
|
||||
|
||||
nukeSoundExplosion()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
foreach( player in level._players )
|
||||
{
|
||||
player playlocalsound( "nuke_explosion" );
|
||||
player playlocalsound( "nuke_wave" );
|
||||
}
|
||||
}
|
||||
|
||||
nukeEffects()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
setDvar( "ui_bomb_timer", 0 );
|
||||
setGameEndTime( 0 );
|
||||
|
||||
level._nukeDetonated = true;
|
||||
level maps\mp\killstreaks\_emp::destroyActiveVehicles( level._nukeInfo.player );
|
||||
|
||||
foreach( player in level._players )
|
||||
{
|
||||
playerForward = anglestoforward( player.angles );
|
||||
playerForward = ( playerForward[0], playerForward[1], 0 );
|
||||
playerForward = VectorNormalize( playerForward );
|
||||
|
||||
nukeDistance = 5000;
|
||||
/# nukeDistance = getDvarInt( "scr_nukeDistance" ); #/
|
||||
|
||||
nukeEnt = Spawn( "script_model", player.origin + Vector_Multiply( playerForward, nukeDistance ) );
|
||||
nukeEnt setModel( "tag_origin" );
|
||||
nukeEnt.angles = ( 0, (player.angles[1] + 180), 90 );
|
||||
|
||||
/#
|
||||
if ( getDvarInt( "scr_nukeDebugPosition" ) )
|
||||
{
|
||||
lineTop = ( nukeEnt.origin[0], nukeEnt.origin[1], (nukeEnt.origin[2] + 500) );
|
||||
thread draw_line_for_time( nukeEnt.origin, lineTop, 1, 0, 0, 10 );
|
||||
}
|
||||
#/
|
||||
|
||||
nukeEnt thread nukeEffect( player );
|
||||
player.nuked = true;
|
||||
}
|
||||
}
|
||||
|
||||
nukeEffect( player )
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
player endon( "disconnect" );
|
||||
|
||||
waitframe();
|
||||
PlayFXOnTagForClients( level._effect[ "nuke_flash" ], self, "tag_origin", player );
|
||||
}
|
||||
|
||||
nukeAftermathEffect()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
level waittill ( "spawning_intermission" );
|
||||
|
||||
afermathEnt = getEntArray( "mp_global_intermission", "classname" );
|
||||
afermathEnt = afermathEnt[0];
|
||||
up = anglestoup( afermathEnt.angles );
|
||||
right = anglestoright( afermathEnt.angles );
|
||||
|
||||
PlayFX( level._effect[ "nuke_aftermath" ], afermathEnt.origin, up, right );
|
||||
}
|
||||
|
||||
nukeSlowMo()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
//SetSlowMotion( <startTimescale>, <endTimescale>, <deltaTime> )
|
||||
setSlowMotion( 1.0, 0.25, 0.5 );
|
||||
level waittill( "nuke_death" );
|
||||
setSlowMotion( 0.25, 1, 2.0 );
|
||||
}
|
||||
|
||||
nukeVision()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
level._nukeVisionInProgress = true;
|
||||
visionSetNaked( "mpnuke", 3 );
|
||||
|
||||
level waittill( "nuke_death" );
|
||||
|
||||
visionSetNaked( "mpnuke_aftermath", 5 );
|
||||
wait 5;
|
||||
level._nukeVisionInProgress = undefined;
|
||||
}
|
||||
|
||||
nukeDeath()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
level notify( "nuke_death" );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone();
|
||||
|
||||
AmbientStop(1);
|
||||
|
||||
foreach( player in level._players )
|
||||
{
|
||||
if ( isAlive( player ) )
|
||||
player thread maps\mp\gametypes\_damage::finishPlayerDamageWrapper( level._nukeInfo.player, level._nukeInfo.player, 999999, 0, "MOD_EXPLOSIVE", "nuke_mp", player.origin, player.origin, "none", 0, 0 );
|
||||
}
|
||||
|
||||
level._postRoundTime = 10;
|
||||
|
||||
nukeEndsGame = true;
|
||||
|
||||
if ( level._teamBased )
|
||||
thread maps\mp\gametypes\_gamelogic::endGame( level._nukeInfo.team, game["strings"]["nuclear_strike"], true );
|
||||
else
|
||||
{
|
||||
if ( isDefined( level._nukeInfo.player ) )
|
||||
thread maps\mp\gametypes\_gamelogic::endGame( level._nukeInfo.player, game["strings"]["nuclear_strike"], true );
|
||||
else
|
||||
thread maps\mp\gametypes\_gamelogic::endGame( level._nukeInfo, game["strings"]["nuclear_strike"], true );
|
||||
}
|
||||
}
|
||||
|
||||
nukeEarthquake()
|
||||
{
|
||||
level endon ( "nuke_cancelled" );
|
||||
|
||||
level waittill( "nuke_death" );
|
||||
|
||||
// TODO: need to get a different position to call this on
|
||||
//earthquake( 0.6, 10, nukepos, 100000 );
|
||||
|
||||
//foreach( player in level.players )
|
||||
//player PlayRumbleOnEntity( "damage_heavy" );
|
||||
}
|
||||
|
||||
|
||||
waitForNukeCancel()
|
||||
{
|
||||
self waittill( "cancel_location" );
|
||||
self setblurforplayer( 0, 0.3 );
|
||||
}
|
||||
|
||||
endSelectionOn( waitfor )
|
||||
{
|
||||
self endon( "stop_location_selection" );
|
||||
self waittill( waitfor );
|
||||
self thread stopNukeLocationSelection( (waitfor == "disconnect") );
|
||||
}
|
||||
|
||||
endSelectionOnGameEnd()
|
||||
{
|
||||
self endon( "stop_location_selection" );
|
||||
level waittill( "game_ended" );
|
||||
self thread stopNukeLocationSelection( false );
|
||||
}
|
||||
|
||||
stopNukeLocationSelection( disconnected )
|
||||
{
|
||||
if ( !disconnected )
|
||||
{
|
||||
self setblurforplayer( 0, 0.3 );
|
||||
self endLocationSelection();
|
||||
self.selectingLocation = undefined;
|
||||
}
|
||||
self notify( "stop_location_selection" );
|
||||
}
|
711
maps/mp/killstreaks/_reaper.gsc
Normal file
711
maps/mp/killstreaks/_reaper.gsc
Normal file
@ -0,0 +1,711 @@
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
precacheString( &"MP_LASE_TARGET_FOR_GUIDED_MORTAR" );
|
||||
precacheString( &"MP_WAIT_FOR_MORTAR_READY" );
|
||||
precacheString( &"MP_MORTAR_ROUNDS_DEPLETED" );
|
||||
precacheString( &"SPLASHES_DESTROYED_REMOTE_MORTAR" );
|
||||
|
||||
precacheModel( "vehicle_predator_b" );
|
||||
precacheItem( "remote_mortar_missile_mp" );
|
||||
precacheItem( "mortar_remote_mp" );
|
||||
precacheItem( "mortar_remote_zoom_mp" );
|
||||
|
||||
precacheShader( "compass_waypoint_bomb" );
|
||||
precacheShader( "viper_locked_box" );
|
||||
PrecacheMiniMapIcon( "compass_objpoint_reaper_friendly" );
|
||||
PrecacheMiniMapIcon( "compass_objpoint_reaper_enemy" );
|
||||
|
||||
level._remote_mortar_fx["laserTarget"] = loadfx("nx/misc/nx_laser_glow");
|
||||
|
||||
level._killstreakFuncs["reaper"] = ::tryUseRemoteMortar;
|
||||
|
||||
/#
|
||||
SetDevDvarIfUninitialized( "scr_remote_mortar_timeout", 40.0 );
|
||||
#/
|
||||
}
|
||||
|
||||
|
||||
tryUseRemoteMortar( lifeId )
|
||||
{
|
||||
if ( isDefined( self.lastStand ) && !self _hasPerk( "specialty_finalstand" ) )
|
||||
{
|
||||
self iPrintLnBold( &"MP_UNAVILABLE_IN_LASTSTAND" );
|
||||
return false;
|
||||
}
|
||||
|
||||
self setUsingRemote( "remote_mortar" );
|
||||
/* result = self maps\mp\killstreaks\_killstreaks::initRideKillstreak();
|
||||
if ( result != "success" )
|
||||
{
|
||||
if ( result != "disconnect" )
|
||||
self clearUsingRemote();
|
||||
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
self maps\mp\_matchdata::logKillstreakEvent( "remote_mortar", self.origin );
|
||||
|
||||
return startRemoteMortar( lifeId );
|
||||
}
|
||||
|
||||
|
||||
startRemoteMortar( lifeId )
|
||||
{
|
||||
remote = spawnRemote( lifeId, self );
|
||||
if ( !isDefined( remote ) )
|
||||
return false;
|
||||
|
||||
self setPlayerData( "reaperHUD", "targetDistance", -1 );
|
||||
|
||||
self remoteRide( remote );
|
||||
|
||||
self thread teamPlayerCardSplash( "used_remote_mortar", self );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
spawnRemote( lifeId, owner )
|
||||
{
|
||||
remote = spawnPlane( owner, "script_model", level._UAVRig getTagOrigin( "tag_origin" ), "compass_objpoint_reaper_friendly", "compass_objpoint_reaper_enemy" );
|
||||
if ( !isDefined( remote ) )
|
||||
return undefined;
|
||||
|
||||
remote setModel( "vehicle_predator_b" );
|
||||
remote.lifeId = lifeId;
|
||||
remote.team = owner.team;
|
||||
remote.owner = owner;
|
||||
remote.numFlares = 1;
|
||||
|
||||
remote setCanDamage( true );
|
||||
remote thread damageTracker();
|
||||
|
||||
remote.heliType = "remote_mortar";
|
||||
|
||||
// for target lists (javelin, stinger, sam, emp, etc)
|
||||
remote.uavType = "remote_mortar";
|
||||
maps\mp\killstreaks\_uav::addUAVModel( remote );
|
||||
|
||||
// same height and radius as the AC130 with random angle and counter rotation
|
||||
zOffset = 6300;
|
||||
angle = randomInt( 360 );
|
||||
radiusOffset = 6100;
|
||||
xOffset = cos( angle ) * radiusOffset;
|
||||
yOffset = sin( angle ) * radiusOffset;
|
||||
angleVector = vectorNormalize( (xOffset,yOffset,zOffset) );
|
||||
angleVector = ( angleVector * 6100 );
|
||||
remote linkTo( level._UAVRig, "tag_origin", angleVector, (0,angle-90,10) );
|
||||
|
||||
remote thread handleDeath( owner );
|
||||
remote thread handleTimeout( owner );
|
||||
remote thread handleOwnerChangeTeam( owner );
|
||||
remote thread handleOwnerDisconnect( owner );
|
||||
remote thread handleIncomingStinger();
|
||||
remote thread handleIncomingSAM();
|
||||
|
||||
return remote;
|
||||
}
|
||||
|
||||
|
||||
lookCenter()
|
||||
{
|
||||
wait( 0.05 );
|
||||
|
||||
lookVec = vectorToAngles( level._UAVRig.origin - self GetEye() );
|
||||
|
||||
self setPlayerAngles( lookVec );
|
||||
}
|
||||
|
||||
|
||||
remoteRide( remote )
|
||||
{
|
||||
self setPlayerData( "reaperHUD", "zoomed", false );
|
||||
self _giveWeapon("mortar_remote_mp");
|
||||
self SwitchToWeapon("mortar_remote_mp");
|
||||
self ThermalVisionFOFOverlayOn();
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( false );
|
||||
|
||||
self PlayerLinkWeaponviewToDelta( remote, "tag_player", 1.0, 35, 35, 15, 55 );
|
||||
self thread lookCenter();
|
||||
|
||||
self thread remoteTargeting( remote );
|
||||
self thread remoteFiring( remote );
|
||||
self thread remoteZoom( remote );
|
||||
}
|
||||
|
||||
|
||||
remoteTargeting( remote )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "disconnect" );
|
||||
remote endon( "remote_done" );
|
||||
remote endon( "death" );
|
||||
|
||||
remote.targetEnt = SpawnFx( level._remote_mortar_fx["laserTarget"], (0,0,0) );
|
||||
remote.targetEnt.icon = remote.targetEnt maps\mp\_entityheadIcons::setHeadIcon( self, "viper_locked_box", (0,0,-270), 100, 100, false, 0.05, false, false, false, false );
|
||||
remote.targetEnt.icon.color = (0.9, 0.7, 0.2);
|
||||
|
||||
/*laserPos = remote getTagOrigin( "tag_player" );
|
||||
remote.laserEnt = Spawn( "script_model", laserPos );
|
||||
remote.laserEnt linkTo( remote, "tag_player", (0,0,0), (0,0,0) );
|
||||
remote.laserEnt LaserOn();*/
|
||||
|
||||
while ( true )
|
||||
{
|
||||
origin = self GetEye();
|
||||
forward = AnglesToForward( self GetPlayerAngles() );
|
||||
endpoint = origin + forward * 15000;
|
||||
traceData = BulletTrace( origin, endpoint, false, remote.targetEnt );
|
||||
if ( isDefined( traceData["position"] ) )
|
||||
{
|
||||
remote.targetEnt.origin = traceData["position"];
|
||||
triggerFX( remote.targetEnt );
|
||||
}
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remoteFiring( remote )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "disconnect" );
|
||||
remote endon( "remote_done" );
|
||||
remote endon( "death" );
|
||||
|
||||
curTime = getTime();
|
||||
lastFireTime = curTime-750;
|
||||
shotsFired = 0;
|
||||
|
||||
while( true )
|
||||
{
|
||||
curTime = getTime();
|
||||
if ( self attackButtonPressed() && ( curTime - lastFireTime > 3000 ) )
|
||||
{
|
||||
shotsFired++;
|
||||
lastFireTime = curTime;
|
||||
self playLocalSound( "stinger_locking" );
|
||||
self PlayRumbleOnEntity( "damage_heavy" );
|
||||
|
||||
origin = self GetEye();
|
||||
forward = AnglesToForward( self GetPlayerAngles() );
|
||||
right = AnglesToRight( self GetPlayerAngles() );
|
||||
offset = origin + ( forward * 100 ) + ( right * -100 );
|
||||
missile = MagicBullet( "remote_mortar_missile_mp", offset, remote.targetEnt.origin, self );
|
||||
|
||||
missile Missile_SetTargetEnt( remote.targetEnt );
|
||||
missile Missile_SetFlightmodeDirect();
|
||||
missile.icon = missile maps\mp\_entityheadIcons::setHeadIcon( self, "compass_waypoint_bomb", (0,0,-10), 10, 10, false, 0.05, false, false, false, false );
|
||||
missile thread remoteMissileDistance( remote );
|
||||
|
||||
remote.missileIcon = missile.icon;
|
||||
|
||||
missile waittill( "death" );
|
||||
|
||||
if ( isDefined( missile.icon ) )
|
||||
{
|
||||
missile.icon destroy();
|
||||
missile.icon = undefined;
|
||||
}
|
||||
self setPlayerData( "reaperHUD", "targetDistance", -1 );
|
||||
|
||||
if ( shotsFired == 14 )
|
||||
break;
|
||||
}
|
||||
else
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
self remoteEndRide( remote );
|
||||
remote thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
remoteZoom( remote )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "disconnect" );
|
||||
remote endon( "remote_done" );
|
||||
remote endon( "death" );
|
||||
|
||||
remote.zoomed = false;
|
||||
|
||||
while ( true )
|
||||
{
|
||||
if ( self adsButtonPressed() )
|
||||
{
|
||||
if ( remote.zoomed == false )
|
||||
{
|
||||
self _giveWeapon("mortar_remote_zoom_mp");
|
||||
self SwitchToWeapon("mortar_remote_zoom_mp");
|
||||
remote.zoomed = true;
|
||||
self setPlayerData( "reaperHUD", "zoomed", true );
|
||||
|
||||
if ( isDefined( remote.targetEnt.icon ) )
|
||||
{
|
||||
remote.targetEnt.icon destroy();
|
||||
remote.targetEnt.icon = undefined;
|
||||
remote.targetEnt.icon = remote.targetEnt maps\mp\_entityheadIcons::setHeadIcon( self, "viper_locked_box", (0,0,-50), 100, 100, false, 0.05, false, false, false, false );
|
||||
remote.targetEnt.icon.color = (0.9, 0.7, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( remote.zoomed == true )
|
||||
{
|
||||
self _giveWeapon("mortar_remote_mp");
|
||||
self SwitchToWeapon("mortar_remote_mp");
|
||||
remote.zoomed = false;
|
||||
self setPlayerData( "reaperHUD", "zoomed", false );
|
||||
|
||||
if ( isDefined( remote.targetEnt.icon ) )
|
||||
{
|
||||
remote.targetEnt.icon destroy();
|
||||
remote.targetEnt.icon = undefined;
|
||||
remote.targetEnt.icon = remote.targetEnt maps\mp\_entityheadIcons::setHeadIcon( self, "viper_locked_box", (0,0,-270), 100, 100, false, 0.05, false, false, false, false );
|
||||
remote.targetEnt.icon.color = (0.9, 0.7, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remoteMissileDistance( remote )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
remote endon( "death" );
|
||||
remote endon( "remote_done" );
|
||||
self endon( "death" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
targetDist = distance( self.origin, remote.targetent.origin );
|
||||
remote.owner setPlayerData( "reaperHUD", "targetDistance", int( targetDist / 12 ) );
|
||||
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remoteEndRide( remote )
|
||||
{
|
||||
if ( isDefined( remote ) )
|
||||
{
|
||||
remote notify( "helicopter_done" );
|
||||
if ( isDefined( remote.laserEnt ) )
|
||||
remote.laserEnt LaserOff();
|
||||
if ( isDefined( remote.targetEnt ) && isDefined( remote.targetEnt.icon ) )
|
||||
{
|
||||
remote.targetEnt.icon destroy();
|
||||
remote.targetEnt.icon = undefined;
|
||||
}
|
||||
if ( isDefined( remote.missileIcon ) )
|
||||
{
|
||||
remote.missileIcon destroy();
|
||||
remote.missileIcon = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
self ThermalVisionFOFOverlayOff();
|
||||
self unlink();
|
||||
self clearUsingRemote();
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( true );
|
||||
|
||||
self switchToWeapon( self getLastWeapon() );
|
||||
weaponList = self GetWeaponsListExclusives();
|
||||
foreach ( weapon in weaponList )
|
||||
self takeWeapon( weapon );
|
||||
}
|
||||
|
||||
|
||||
handleTimeout( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
owner endon( "disconnect" );
|
||||
self endon( "death" );
|
||||
|
||||
lifeSpan = 40.0;
|
||||
/#
|
||||
lifeSpan = GetDvarInt( "scr_remote_mortar_timeout", lifeSpan );
|
||||
#/
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( lifeSpan );
|
||||
|
||||
if ( isDefined( owner ) )
|
||||
owner remoteEndRide( self );
|
||||
self thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
handleDeath( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
owner endon( "disconnect" );
|
||||
self endon( "remote_done" );
|
||||
|
||||
self waittill( "death" );
|
||||
|
||||
if ( isDefined( owner ) )
|
||||
owner remoteEndRide( self );
|
||||
level thread removeRemote( self );
|
||||
}
|
||||
|
||||
|
||||
handleOwnerChangeTeam( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "remote_done" );
|
||||
self endon( "death" );
|
||||
owner endon( "disconnect" );
|
||||
|
||||
owner waittill_any( "joined_team", "joined_spectators" );
|
||||
|
||||
if ( isDefined( owner ) )
|
||||
owner remoteEndRide( self );
|
||||
self thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
handleOwnerDisconnect( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "remote_done" );
|
||||
self endon( "death" );
|
||||
|
||||
owner waittill( "disconnect" );
|
||||
|
||||
self thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
removeRemote( remote )
|
||||
{
|
||||
self notify( "remote_removed" );
|
||||
|
||||
if ( isDefined( remote.targetEnt ) )
|
||||
{
|
||||
if ( isDefined( remote.targetEnt.icon ) )
|
||||
{
|
||||
remote.targetEnt.icon destroy();
|
||||
remote.targetEnt.icon = undefined;
|
||||
}
|
||||
remote.targetEnt delete();
|
||||
}
|
||||
if ( isDefined( remote.laserEnt ) )
|
||||
remote.laserEnt delete();
|
||||
|
||||
if( IsDefined( remote ) )
|
||||
{
|
||||
remote delete();
|
||||
maps\mp\killstreaks\_uav::removeUAVModel( remote );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
remoteLeave()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
|
||||
self notify( "remote_done" );
|
||||
|
||||
self unlink();
|
||||
destPoint = self.origin + ( AnglesToForward( self.angles ) * 20000 );
|
||||
self moveTo( destPoint, 30 );
|
||||
PlayFXOnTag( level._effect[ "ac130_engineeffect" ] , self, "tag_origin" );
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 3 );
|
||||
|
||||
self moveTo( destPoint, 4, 4, 0.0 );
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 4 );
|
||||
|
||||
level thread removeRemote( self );
|
||||
}
|
||||
|
||||
|
||||
// Entities spawned from SpawnPlane do not respond to pre-damage callbacks
|
||||
// so we have to wait until we get the post-damage event.
|
||||
//
|
||||
// Because the damage has already happened by the time we find out about it,
|
||||
// we need to use an artificially high health value, restore it on erroneous damage
|
||||
// events and track a virtual damage taken against a virtual max health.
|
||||
damageTracker()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self.owner endon( "disconnect" );
|
||||
|
||||
self.health = 999999; // keep it from dying anywhere in code
|
||||
self.maxHealth = 1000; // this is the health we'll check
|
||||
self.damageTaken = 0; // how much damage has it taken
|
||||
|
||||
while( true )
|
||||
{
|
||||
self waittill( "damage", damage, attacker, direction_vec, point, meansOfDeath, modelName, tagName, partName, iDFlags, weapon );
|
||||
|
||||
// don't allow people to destroy things on their team if FF is off
|
||||
if ( !maps\mp\gametypes\_weapons::friendlyFireCheck( self.owner, attacker ) )
|
||||
continue;
|
||||
|
||||
if ( !IsDefined( self ) )
|
||||
return;
|
||||
|
||||
if ( isDefined( iDFlags ) && ( iDFlags & level._iDFLAGS_PENETRATION ) )
|
||||
self.wasDamagedFromBulletPenetration = true;
|
||||
|
||||
self.wasDamaged = true;
|
||||
|
||||
modifiedDamage = damage;
|
||||
|
||||
if( IsPlayer( attacker ) )
|
||||
{
|
||||
attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "" );
|
||||
|
||||
if( meansOfDeath == "MOD_RIFLE_BULLET" || meansOfDeath == "MOD_PISTOL_BULLET" )
|
||||
{
|
||||
if ( attacker _hasPerk( "specialty_armorpiercing" ) )
|
||||
modifiedDamage += damage * level._armorPiercingMod;
|
||||
}
|
||||
}
|
||||
|
||||
if( IsDefined( weapon ) )
|
||||
{
|
||||
switch( weapon )
|
||||
{
|
||||
case "stinger_mp":
|
||||
case "javelin_mp":
|
||||
self.largeProjectileDamage = true;
|
||||
modifiedDamage = self.maxhealth + 1;
|
||||
break;
|
||||
|
||||
case "sam_projectile_mp":
|
||||
self.largeProjectileDamage = true;
|
||||
modifiedDamage *= 2.0; // takes about 1 burst of sam rockets
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
self.damageTaken += modifiedDamage;
|
||||
|
||||
if ( self.damageTaken >= self.maxHealth )
|
||||
{
|
||||
if ( isPlayer( attacker ) && ( !isDefined( self.owner ) || attacker != self.owner ) )
|
||||
{
|
||||
self Hide();
|
||||
forward = ( AnglesToRight( self.angles ) * 200 );
|
||||
playFx ( level._uav_fx[ "explode" ], self.origin, forward );
|
||||
|
||||
attacker notify( "destroyed_killstreak", weapon );
|
||||
thread teamPlayerCardSplash( "callout_destroyed_remote_mortar", attacker );
|
||||
//attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 50, weapon, meansOfDeath );
|
||||
//attacker thread maps\mp\gametypes\_rank::xpEventPopup( &"SPLASHES_DESTROYED_REMOTE_MORTAR" );
|
||||
//thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, meansOfDeath, weapon );
|
||||
}
|
||||
|
||||
self notify( "death" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
handleIncomingStinger() // self == remote mortar
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
self endon ( "death" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
level waittill ( "stinger_fired", player, missile, lockTarget );
|
||||
|
||||
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
|
||||
continue;
|
||||
|
||||
missile thread stingerProximityDetonate( lockTarget, player );
|
||||
}
|
||||
}
|
||||
|
||||
stingerProximityDetonate( missileTarget, player ) // self == missile
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
missileTarget.owner PlayLocalSound( "missile_incoming" );
|
||||
|
||||
self Missile_SetTargetEnt( missileTarget );
|
||||
|
||||
minDist = Distance( self.origin, missileTarget GetPointInBounds( 0, 0, 0 ) );
|
||||
lastCenter = missileTarget GetPointInBounds( 0, 0, 0 );
|
||||
|
||||
while( true )
|
||||
{
|
||||
// already destroyed
|
||||
if( !IsDefined( missileTarget ) )
|
||||
center = lastCenter;
|
||||
else
|
||||
center = missileTarget GetPointInBounds( 0, 0, 0 );
|
||||
|
||||
lastCenter = center;
|
||||
|
||||
curDist = Distance( self.origin, center );
|
||||
|
||||
if( curDist < 3000 && missileTarget.numFlares > 0 )
|
||||
{
|
||||
missileTarget.numFlares--;
|
||||
|
||||
missileTarget thread maps\mp\killstreaks\_helicopter::playFlareFx();
|
||||
newTarget = missileTarget maps\mp\killstreaks\_helicopter::deployFlares();
|
||||
|
||||
self Missile_SetTargetEnt( newTarget );
|
||||
missileTarget = newTarget;
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
missileTarget.owner StopLocalSound( "missile_incoming" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( curDist < minDist )
|
||||
minDist = curDist;
|
||||
|
||||
if( curDist > minDist )
|
||||
{
|
||||
if( curDist > 1536 )
|
||||
return;
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
{
|
||||
missileTarget.owner stopLocalSound( "missile_incoming" );
|
||||
|
||||
if( level._teambased )
|
||||
{
|
||||
if( missileTarget.team != player.team )
|
||||
RadiusDamage( self.origin, 1000, 1000, 1000, player, "MOD_EXPLOSIVE", "stinger_mp" );
|
||||
}
|
||||
else
|
||||
{
|
||||
RadiusDamage( self.origin, 1000, 1000, 1000, player, "MOD_EXPLOSIVE", "stinger_mp" );
|
||||
}
|
||||
}
|
||||
|
||||
self Hide();
|
||||
|
||||
wait( 0.05 );
|
||||
self delete();
|
||||
}
|
||||
|
||||
wait ( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
handleIncomingSAM() // self == remote mortar
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
self endon ( "death" );
|
||||
|
||||
while( true )
|
||||
{
|
||||
level waittill ( "sam_fired", player, missileGroup, lockTarget );
|
||||
|
||||
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
|
||||
continue;
|
||||
|
||||
level thread samProximityDetonate( lockTarget, player, missileGroup );
|
||||
}
|
||||
}
|
||||
|
||||
samProximityDetonate( missileTarget, player, missileGroup )
|
||||
{
|
||||
missileTarget endon( "death" );
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
missileTarget.owner PlayLocalSound( "missile_incoming" );
|
||||
|
||||
sam_projectile_damage = 150; // this should match the gdt entry
|
||||
sam_projectile_damage_radius = 1000;
|
||||
|
||||
minDist = [];
|
||||
for( i = 0; i < missileGroup.size; i++ )
|
||||
{
|
||||
if( IsDefined( missileGroup[ i ] ) )
|
||||
minDist[ i ] = Distance( missileGroup[ i ].origin, missileTarget GetPointInBounds( 0, 0, 0 ) );
|
||||
else
|
||||
minDist[ i ] = undefined;
|
||||
}
|
||||
|
||||
while( true )
|
||||
{
|
||||
center = missileTarget GetPointInBounds( 0, 0, 0 );
|
||||
|
||||
curDist = [];
|
||||
for( i = 0; i < missileGroup.size; i++ )
|
||||
{
|
||||
if( IsDefined( missileGroup[ i ] ) )
|
||||
curDist[ i ] = Distance( missileGroup[ i ].origin, center );
|
||||
}
|
||||
|
||||
for( i = 0; i < curDist.size; i++ )
|
||||
{
|
||||
if( IsDefined( curDist[ i ] ) )
|
||||
{
|
||||
// if one of the missiles in the group get close, set off flares and redirect them all
|
||||
if( curDist[ i ] < 3000 && missileTarget.numFlares > 0 )
|
||||
{
|
||||
missileTarget.numFlares--;
|
||||
|
||||
missileTarget thread maps\mp\killstreaks\_helicopter::playFlareFx();
|
||||
newTarget = missileTarget maps\mp\killstreaks\_helicopter::deployFlares();
|
||||
|
||||
for( j = 0; j < missileGroup.size; j++ )
|
||||
{
|
||||
if( IsDefined( missileGroup[ j ] ) )
|
||||
{
|
||||
missileGroup[ j ] Missile_SetTargetEnt( newTarget );
|
||||
}
|
||||
}
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
missileTarget.owner StopLocalSound( "missile_incoming" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if( curDist[ i ] < minDist[ i ] )
|
||||
minDist[ i ] = curDist[ i ];
|
||||
|
||||
if( curDist[ i ] > minDist[ i ] )
|
||||
{
|
||||
if( curDist[ i ] > 1536 )
|
||||
return;
|
||||
|
||||
if( IsDefined( missileTarget.owner ) )
|
||||
{
|
||||
missileTarget.owner StopLocalSound( "missile_incoming" );
|
||||
|
||||
if( level._teambased )
|
||||
{
|
||||
if( missileTarget.team != player.team )
|
||||
RadiusDamage( missileGroup[ i ].origin, sam_projectile_damage_radius, sam_projectile_damage, sam_projectile_damage, player, "MOD_EXPLOSIVE", "sam_projectile_mp" );
|
||||
}
|
||||
else
|
||||
{
|
||||
RadiusDamage( missileGroup[ i ].origin, sam_projectile_damage_radius, sam_projectile_damage, sam_projectile_damage, player, "MOD_EXPLOSIVE", "sam_projectile_mp" );
|
||||
}
|
||||
}
|
||||
|
||||
missileGroup[ i ] Hide();
|
||||
|
||||
wait ( 0.05 );
|
||||
missileGroup[ i ] delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wait ( 0.05 );
|
||||
}
|
||||
}
|
774
maps/mp/killstreaks/_remotedog.gsc
Normal file
774
maps/mp/killstreaks/_remotedog.gsc
Normal file
@ -0,0 +1,774 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
DOG_TIMEOUT_SEC = 45;
|
||||
DOG_HUD_TIMER_POS_X = 0;
|
||||
DOG_HUD_TIMER_POS_Y = -35;
|
||||
DOG_TURRET_MAX_TARGETING_RANGE = 600; // 45 feet
|
||||
DOG_TURRET_SPAWN_GRACE_TIME = 3; // dog wont shoot any anyone who hasn't been spawned for 3 seconds
|
||||
DOG_TURRET_MIN_SHOTS = 10; // minimum shots to fire at a player
|
||||
DOG_TURRET_MAX_SHOTS = 20; // maximum shots to fire at a player
|
||||
DOG_TURRET_FIRE_DELAY = .1; // how long to wait between shots at a target
|
||||
DOG_TURRET_MIN_BARRAGE_DELAY = 0; // how long to wait between firing bursts of shots at a target
|
||||
DOG_TURRET_MAX_BARRAGE_DELAY = .1; // how long between burts of shots
|
||||
DOG_TURRET_MAX_YAW = 60; // how far the turret can turn from the dogs centerline
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
init()
|
||||
{
|
||||
level._killstreakFuncs["remote_dog"] = ::tryRemoteDog;
|
||||
level._remoteDogVehicleInfo = "PROTO_nx_remote_dog_play_mp";
|
||||
level._remoteDogVehicleModel = "prototype_vehicle_remotedog_vehicle"; // "defaultvehicle"
|
||||
level._remoteDogScriptModel = "prototype_vehicle_remotedog";
|
||||
level._remoteDogMoveAnim = "german_shepherd_run";
|
||||
level._remoteDogIdleAnim = "german_shepherd_idle";
|
||||
level._remoteDogTranProp = "miniuav_transition_prop";
|
||||
level._remoteDogTurretInfo = "proto_robot_dog_turret_mp";
|
||||
level._remoteDogTurretModel = "proto_remotedog_turret";
|
||||
level._remoteDogFOV = 120;
|
||||
level._remoteDogHealth = 200;
|
||||
level._remoteDogAmmo = 100;
|
||||
level._remoteDogFireRate = 1; // in tenths of a second, so 10 is fires once a second
|
||||
level._remoteDogCrossHair = "ac130_overlay_25mm";
|
||||
|
||||
PreCacheItem( level._remoteDogTranProp );
|
||||
precacheString( &"NX_MINIUAV_USE_DRONE" );
|
||||
PreCacheShader( "ac130_overlay_grain" );
|
||||
PreCacheShader( level._remoteDogCrossHair );
|
||||
|
||||
precacheVehicle( level._remoteDogVehicleInfo );
|
||||
precacheModel( level._remoteDogVehicleModel );
|
||||
precacheMpAnim( level._remoteDogMoveAnim );
|
||||
precacheMpAnim( level._remoteDogIdleAnim );
|
||||
precacheModel( level._remoteDogScriptModel );
|
||||
precacheTurret( level._remoteDogTurretInfo );
|
||||
precacheModel( level._remoteDogTurretModel );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogDebugPrint( msg )
|
||||
{
|
||||
IPrintLnBold( msg );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
tryRemoteDog( lifeId )
|
||||
{
|
||||
self thread remoteDogStartup(); // Kick of main UAV loop.
|
||||
msg = self waittill_any_return( "death", "cleanup_remote_dog" ); // Wait for death or timeout.
|
||||
|
||||
if( msg == "cleanup_remote_dog" )
|
||||
{
|
||||
// Wait for weapon transition to happen.
|
||||
wait 2.0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogPlayerEventListenerThread()
|
||||
{
|
||||
self waittill( "exit_remote_dog" );
|
||||
self.remotedog notify( "exit_remote_dog" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogStartup()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "remote_dog_time_is_up" );
|
||||
self endon( "remote_dog_out_of_ammo" );
|
||||
|
||||
// self NotifyOnPlayerCommand( "switch_to_remote_dog", "+actionslot 4" );
|
||||
|
||||
self DisableOffhandWeapons();
|
||||
self._dogPlayerOrigin = self GetOrigin();
|
||||
self._dogPlayerAngles = self GetPlayerAngles();
|
||||
|
||||
// Wait for transition anim to finish.
|
||||
wait 1.75;
|
||||
|
||||
// Enter the Dawg.
|
||||
pos = self._dogPlayerOrigin + ( 0, 0, 50 );
|
||||
|
||||
// setup vehicle
|
||||
self.remotedog = spawnVehicle( level._remoteDogVehicleModel, "test_dog", level._remoteDogVehicleInfo, pos, self._dogPlayerAngles );
|
||||
self.remotedog.health = level._remoteDogHealth;
|
||||
self.remotedog.maxhealth = self.remotedog.health;
|
||||
self.remotedog setCanDamage( true );
|
||||
self.remotedog.owner = self;
|
||||
self.remotedog.team = self.team;
|
||||
self.remotedog.ammo = level._remoteDogAmmo;
|
||||
self.remotedog.fireRate = level._remoteDogFireRate;
|
||||
self.remotedog.damageCallback = ::Callback_DogDamage;
|
||||
// hide the remote dog, we're going to attach another model to it
|
||||
self.remotedog Hide();
|
||||
|
||||
// setup dog model
|
||||
self.remotedog.remoteDogModel = spawn( "script_model", pos );
|
||||
self.remotedog.remoteDogModel.owner = self;
|
||||
self.remotedog.remoteDogModel setModel( level._remoteDogScriptModel );
|
||||
self.remotedog.remoteDogModel ScriptModelPlayAnim( level._remoteDogIdleAnim );
|
||||
self.remotedog.remoteDogModel.angles = self._dogPlayerAngles;
|
||||
self.remotedog.currAnim = level._remoteDogIdleAnim;
|
||||
self.remotedog.remoteDogModel linkto( self.remotedog );
|
||||
|
||||
// setup hud and stuff
|
||||
self.remotedog notify( "stop_turret_shoot" );
|
||||
self.in_dog = true;
|
||||
self thread remotedogHud();
|
||||
self CameraLinkTo( self.remotedog, "tag_player" );
|
||||
self.remote_dog_orig_fov = GetDvarFloat( "cg_fov" );
|
||||
self setClientDvar( "cg_fov", level._remoteDogFOV );
|
||||
self ThermalVisionFOFOverlayOn();
|
||||
self visionSetNakedForPlayer( "cheat_bw", 0 );
|
||||
|
||||
// create the turret for the dawg
|
||||
turretPoint = self.remotedog getTagOrigin( "TAG_TURRET" );
|
||||
self.remotedog.turret = spawnTurret( "misc_turret", turretPoint, level._remoteDogTurretInfo );
|
||||
self.remotedog.turret linkTo( self.remotedog, "TAG_TURRET", (0,0,0), (0,0,0) );
|
||||
self.remotedog.turret setModel( level._remoteDogTurretModel );
|
||||
self.remotedog.turret.angles = self.remotedog.angles;
|
||||
self.remotedog.turret.owner = self.remotedog.owner;
|
||||
self.remotedog.turret makeTurretInoperable();
|
||||
self.remotedog.turret SetDefaultDropPitch( 0 );
|
||||
//self.remotedog.turret.owner = self;
|
||||
|
||||
// find a point to for the turret to look at when it isn't trying to fire
|
||||
offset = turretPoint - self.remotedog.origin;
|
||||
neutralTargetEnt = spawn("script_origin", self.remotedog.turret getTagOrigin("tag_flash") );
|
||||
neutralTargetEnt linkTo( self, "tag_origin", offset, (0,0,0) );
|
||||
neutralTargetEnt hide();
|
||||
self.remotedog.neutralTarget = neutralTargetEnt;
|
||||
|
||||
// spawn a thread to control the turret
|
||||
self.remotedog thread remoteDogFindTargets();
|
||||
|
||||
// get them controls hooked up!
|
||||
// self ControlsLinkTo( self.remotedog );
|
||||
self MiniUAVOn( self.remotedog );
|
||||
|
||||
// Kick off timer.
|
||||
self hudRemoteDogTimer( DOG_TIMEOUT_SEC );
|
||||
self.remotedog thread RemoteDogWaitForTimeout( DOG_TIMEOUT_SEC );
|
||||
|
||||
|
||||
// loop for the dog
|
||||
self thread remoteDogLoop( self.remotedog );
|
||||
|
||||
// setup a thread to listen for the exit
|
||||
self thread remoteDogPlayerEventListenerThread();
|
||||
|
||||
self.remotedog thread remoteDogExitCleanup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogExitCleanup()
|
||||
{
|
||||
remoteDogDebugPrint( "remoteDogExitCleanup()" );
|
||||
msg = self waittill_any_return( "death", "exit_remote_dog", "remote_dog_time_is_up", "remote_dog_out_of_ammo" ); // Wait for either way of exiting a uav.
|
||||
remoteDogDebugPrint( "Running cleanup after msg " + msg );
|
||||
self.owner thread remoteDogExitPlayer();
|
||||
self notify( "cleanup_remote_dog" );
|
||||
self.owner notify( "cleanup_remote_dog" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogFindTargets()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "cleanup_remote_dog" );
|
||||
|
||||
println( "Geting Targets" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
targets = [];
|
||||
players = level._players;
|
||||
|
||||
for (i = 0; i <= players.size; i++)
|
||||
{
|
||||
if ( isDogTarget( players[i] ) && isdefined( players[i] ) )
|
||||
{
|
||||
targets[targets.size] = players[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
wait( .05 );
|
||||
}
|
||||
if ( targets.size > 0 )
|
||||
{
|
||||
self acquireTarget( targets );
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
wait( .05 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
isDogTarget( potentialTarget )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( !isalive( potentialTarget ) || potentialTarget.sessionstate != "playing" )
|
||||
return false;
|
||||
|
||||
if ( !isdefined( potentialTarget.pers["team"] ) )
|
||||
return false;
|
||||
|
||||
if ( potentialTarget == self.owner )
|
||||
return false;
|
||||
|
||||
if ( distanceSquared( potentialTarget.origin , self.origin ) > DOG_TURRET_MAX_TARGETING_RANGE*DOG_TURRET_MAX_TARGETING_RANGE )
|
||||
return false;
|
||||
|
||||
if ( level._teamBased && potentialTarget.pers["team"] == self.team )
|
||||
return false;
|
||||
|
||||
if ( potentialTarget.pers["team"] == "spectator" )
|
||||
return false;
|
||||
|
||||
if ( isdefined( potentialTarget.spawntime ) && ( gettime() - potentialTarget.spawntime )/1000 <= DOG_TURRET_SPAWN_GRACE_TIME )
|
||||
return false;
|
||||
|
||||
// check to see if they are in our yaw range
|
||||
vecToTarget = potentialTarget.origin - self.origin;
|
||||
targetYaw = AngleClamp( VectorToYaw( vecToTarget ) );
|
||||
turretYaw = AngleClamp( self.angles[1] );
|
||||
degrees = abs( targetYaw - self.angles[1] );
|
||||
degrees = AngleClamp( degrees );
|
||||
if( degrees > DOG_TURRET_MAX_YAW && ( 360 - degrees ) > DOG_TURRET_MAX_YAW )
|
||||
{
|
||||
// println( "bad degrees " + degrees + " angles " + turretYaw + " target yaw " + targetYaw );
|
||||
return false;
|
||||
}
|
||||
// println( "good degrees " + degrees + " angles " + turretYaw + " target yaw " + targetYaw );
|
||||
|
||||
|
||||
if ( isDefined( self ) )
|
||||
{
|
||||
minTurretEye = self.turret.origin + ( 0, 0, 64 );
|
||||
minTurretCanSeeTarget = potentialTarget sightConeTrace( minTurretEye, self );
|
||||
|
||||
if ( minTurretCanSeeTarget < 1 )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
getBestTarget( targets )
|
||||
{
|
||||
self endon( "death" );
|
||||
origin = self.origin;
|
||||
|
||||
closest = undefined;
|
||||
bestTarget = undefined;
|
||||
|
||||
foreach ( targ in targets )
|
||||
{
|
||||
curDist = Distance( self.origin, targ.origin );
|
||||
|
||||
if ( !isDefined( closest ) )
|
||||
{
|
||||
closest = curDist;
|
||||
bestTarget = targ;
|
||||
}
|
||||
else if ( closest > curDist )
|
||||
{
|
||||
closest = curDist;
|
||||
bestTarget = targ;
|
||||
}
|
||||
}
|
||||
return ( bestTarget );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
acquireTarget( targets )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( targets.size == 1 )
|
||||
{
|
||||
self.bestTarget = targets[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.bestTarget = self getBestTarget( targets );
|
||||
}
|
||||
|
||||
self notify( "acquiringTarget" );
|
||||
self.turret SetTargetEntity( self.bestTarget, ( 0,0,42 ) ); // sets turret to target entity
|
||||
wait( .15 );
|
||||
self thread fireOnTarget(); // fires on current target.
|
||||
self thread watchTargetDeath( targets ); //abandons target when target killed
|
||||
self thread watchTargetDistance( targets );
|
||||
self thread watchTargetAngle( targets );
|
||||
self thread watchTargetThreat( self.bestTarget );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
fireOnTarget()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "abandonedTarget" );
|
||||
self endon( "killedTarget" );
|
||||
noTargTime = undefined;
|
||||
acquiredTime = getTime();
|
||||
|
||||
if ( !isDefined( self.bestTarget ) )
|
||||
{
|
||||
println("No Targ to fire on");
|
||||
return;
|
||||
}
|
||||
|
||||
println("firing on best target");
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if ( !isDefined ( self.turret getTurretTarget( true ) ) )
|
||||
{
|
||||
if ( !isDefined( noTargTime ) )
|
||||
noTargTime = getTime();
|
||||
|
||||
curTime = getTime();
|
||||
|
||||
if ( noTargTime - curTime > 1 )
|
||||
{
|
||||
noTargTime = undefined;
|
||||
self thread explicitAbandonTarget();
|
||||
return;
|
||||
}
|
||||
|
||||
println("Waiting because the turret doesnt have a target" );
|
||||
|
||||
wait ( .5 );
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
numShots = randomIntRange( DOG_TURRET_MIN_SHOTS, DOG_TURRET_MAX_SHOTS );
|
||||
for ( i = 0; i < numShots; i++ )
|
||||
{
|
||||
println( "actually shooting turret" );
|
||||
self.turret ShootTurret();
|
||||
wait ( DOG_TURRET_FIRE_DELAY );
|
||||
}
|
||||
wait ( randomFloatRange( DOG_TURRET_MIN_BARRAGE_DELAY, DOG_TURRET_MAX_BARRAGE_DELAY ) );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
watchTargetDeath( targets )
|
||||
{
|
||||
self endon( "abandonedTarget" );
|
||||
self endon( "death" );
|
||||
if ( !isDefined( self.bestTarget ) )
|
||||
return;
|
||||
|
||||
self.bestTarget waittill( "death" );
|
||||
|
||||
self notify( "killedTarget" );
|
||||
println( "Killed Target" );
|
||||
|
||||
self.bestTarget = undefined;
|
||||
self.turret ClearTargetEntity();
|
||||
self remoteDogFindTargets();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
watchTargetAngle( targets )
|
||||
{
|
||||
self endon( "abandonedTarget" );
|
||||
self endon( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( !isDefined( self.bestTarget ) )
|
||||
return;
|
||||
|
||||
// check to see if they are in our yaw range
|
||||
vecToTarget = self.bestTarget.origin - self.origin;
|
||||
targetYaw = AngleClamp( VectorToYaw( vecToTarget ) );
|
||||
turretYaw = AngleClamp( self.angles[1] );
|
||||
degrees = abs( targetYaw - self.angles[1] );
|
||||
degrees = AngleClamp( degrees );
|
||||
if( degrees > DOG_TURRET_MAX_YAW && ( 360 - degrees ) > DOG_TURRET_MAX_YAW )
|
||||
{
|
||||
println( "Abandon! degrees " + degrees + " angles " + self.angles[1] + " target yaw " + targetYaw );
|
||||
self thread explicitAbandonTarget();
|
||||
return;
|
||||
}
|
||||
wait ( 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
watchTargetDistance( targets )
|
||||
{
|
||||
self endon( "abandonedTarget" );
|
||||
self endon( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( !isDefined( self.bestTarget ) )
|
||||
return;
|
||||
|
||||
trace = BulletTrace( self.turret.origin, self.bestTarget.origin, false, self );
|
||||
traceDistance = Distance(self.origin, trace["position"] );
|
||||
|
||||
if ( traceDistance > DOG_TURRET_MAX_TARGETING_RANGE )
|
||||
{
|
||||
println( "TARGET DIST TOO FAR!!!" );
|
||||
self thread explicitAbandonTarget();
|
||||
return;
|
||||
}
|
||||
println( traceDistance );
|
||||
wait ( 2 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
watchTargetThreat( curTarget )
|
||||
{
|
||||
self endon( "abandonedTarget" );
|
||||
self endon( "death" );
|
||||
self endon( "killedTarget" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
targets = [];
|
||||
players = level._players;
|
||||
|
||||
for (i = 0; i <= players.size; i++)
|
||||
{
|
||||
if ( isDogTarget( players[i] ) )
|
||||
{
|
||||
if( !isdefined( players[i] ) )
|
||||
continue;
|
||||
|
||||
if( !isdefined(curTarget) )
|
||||
return;
|
||||
|
||||
traceOldTarg = Distance(self.origin, CurTarget.origin );
|
||||
traceNewTarg = Distance(self.origin, players[i].origin );
|
||||
|
||||
if ( traceNewTarg < traceOldTarg )
|
||||
{
|
||||
self thread explicitAbandonTarget();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wait( .05 );
|
||||
}
|
||||
|
||||
wait( .25 );
|
||||
}
|
||||
}
|
||||
|
||||
explicitAbandonTarget( noNewTarget )
|
||||
{
|
||||
self notify( "abandonedTarget" );
|
||||
|
||||
println( "ABANDONED TARGET" );
|
||||
|
||||
self.bestTarget = undefined;
|
||||
self.turret ClearTargetEntity();
|
||||
|
||||
if ( isDefined(noNewTarget) && noNewTarget )
|
||||
return;
|
||||
|
||||
self thread remoteDogFindTargets();
|
||||
return;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogLoop( vehicle )
|
||||
{
|
||||
self endon( "death" );
|
||||
vehicle endon( "cleanup_remote_dog" );
|
||||
|
||||
self NotifyOnPlayerCommand( "exit_remote_dog", "+usereload" ); // BUTTON_X
|
||||
|
||||
vehicle._oldOrigin = vehicle.origin;
|
||||
vehicle.fireCycle = 0;
|
||||
|
||||
while ( isalive( self ) )
|
||||
{
|
||||
if( vehicle.fireCycle > 0 )
|
||||
{
|
||||
vehicle.fireCycle = vehicle.fireCycle - 1;
|
||||
}
|
||||
|
||||
// steal the player's angles to control turning the dog, for now...
|
||||
angles = vehicle.angles;
|
||||
player_angles = self GetPlayerAngles();
|
||||
angles = ( player_angles[0], angles[1], angles[2] );
|
||||
target = vehicle.origin + vector_multiply( AnglesToForward( angles ), 2000.0 );
|
||||
|
||||
// don't do this anymore, the turret is auto targetting now
|
||||
// vehicle SetTurretTargetVec( target );
|
||||
|
||||
vehicle.remoteDogModel.angels = vehicle.angles;
|
||||
|
||||
// no more attack buttons to shoot
|
||||
/*
|
||||
if( self AttackButtonPressed() )
|
||||
{
|
||||
if( vehicle.ammo > 0 && vehicle.fireCycle == 0)
|
||||
{
|
||||
vehicle fireweapon();
|
||||
vehicle.fireCycle = vehicle.fireRate;
|
||||
vehicle.ammo = vehicle.ammo - 1;
|
||||
// out of ammo! lets get out of this thing!
|
||||
if( vehicle.ammo == 0 )
|
||||
{
|
||||
self thread remotedogOutOfAmmoThead( vehicle );
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if( distance( vehicle._oldOrigin, vehicle.origin ) > 0 )
|
||||
{
|
||||
if( vehicle.currAnim != level._remoteDogMoveAnim )
|
||||
{
|
||||
vehicle.remoteDogModel ScriptModelPlayAnim( level._remoteDogMoveAnim );
|
||||
vehicle.currAnim = level._remoteDogMoveAnim;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( vehicle.currAnim != level._remoteDogIdleAnim )
|
||||
{
|
||||
vehicle.remoteDogModel ScriptModelPlayAnim( level._remoteDogIdleAnim );
|
||||
vehicle.currAnim = level._remoteDogIdleAnim;
|
||||
}
|
||||
}
|
||||
|
||||
vehicle._oldOrigin = vehicle.origin;
|
||||
wait 0.1;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remotedogOutOfAmmoThead( vehicle )
|
||||
{
|
||||
remoteDogDebugPrint( "remotedogOutOfAmmoThead() out of ammo!" );
|
||||
vehicle endon( "cleanup_remote_dog" );
|
||||
wait 2;
|
||||
vehicle notify( "remote_dog_out_of_ammo" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
Callback_DogDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName )
|
||||
{
|
||||
remoteDogDebugPrint( "damage callback" );
|
||||
if ( ( attacker == self || ( isDefined( attacker.pers ) && attacker.pers["team"] == self.team ) ) && attacker != self.owner )
|
||||
return;
|
||||
|
||||
remoteDogDebugPrint( "damaged dog! " + damage );
|
||||
self Vehicle_FinishDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remoteDogExitPlayer()
|
||||
{
|
||||
// cleanup the models
|
||||
self.remotedog.remoteDogModel Unlink();
|
||||
self.remotedog.remoteDogModel Delete();
|
||||
|
||||
// cleanup the actual things
|
||||
self.remotedog.turret Delete();
|
||||
self.remotedog Delete();
|
||||
|
||||
self ThermalVisionFOFOverlayOff();
|
||||
self CameraUnlink();
|
||||
self setClientDvar( "cg_fov", self.remote_dog_orig_fov );
|
||||
self MiniUAVOff();
|
||||
// self ControlsUnlink();
|
||||
self visionSetNakedForPlayer( getDvar( "mapname" ), 0 );
|
||||
self setVelocity(( 0, 0, 0 ));
|
||||
self setOrigin( self._dogPlayerOrigin );
|
||||
self setPlayerAngles( self._dogPlayerAngles );
|
||||
self switchToWeapon( self._pre_killstreak_weapon_name );
|
||||
self destroyRemoteDogTimer();
|
||||
wait 2.0;
|
||||
self EnableOffhandWeapons();
|
||||
self.in_dog = false;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
remotedogHud()
|
||||
{
|
||||
/*
|
||||
crossHair = newClientHudElem( self );
|
||||
crossHair.x = 0;
|
||||
crossHair.y = 0;
|
||||
crossHair.alignX = "center";
|
||||
crossHair.alignY = "middle";
|
||||
crossHair.horzAlign = "center";
|
||||
crossHair.vertAlign = "middle";
|
||||
crossHair setshader( level._remoteDogCrossHair, 640, 480 );
|
||||
static = NewClientHudElem( self );
|
||||
static.horzAlign = "fullscreen";
|
||||
static.vertAlign = "fullscreen";
|
||||
static SetShader( "ac130_overlay_grain", 640, 480 );
|
||||
|
||||
self waittill( "cleanup_remote_dog" ); // Wait for either way of exiting a uav.
|
||||
crossHair Destroy();
|
||||
*/
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
hudRemoteDogTimer( duration )
|
||||
{
|
||||
remoteDogDebugPrint( "hudRemoteDogTimer()" );
|
||||
self.remoteDogTimer = newClientHudElem( self );
|
||||
self.remoteDogTimer.x = DOG_HUD_TIMER_POS_X;
|
||||
self.remoteDogTimer.y = DOG_HUD_TIMER_POS_Y;
|
||||
self.remoteDogTimer.alignX = "center";
|
||||
self.remoteDogTimer.alignY = "bottom";
|
||||
self.remoteDogTimer.horzAlign = "center_adjustable";
|
||||
self.remoteDogTimer.vertAlign = "bottom_adjustable";
|
||||
self.remoteDogTimer.fontScale = 2.5;
|
||||
self.remoteDogTimer setTimer( 1.0 );
|
||||
self.remoteDogTimer.alpha = 1.0;
|
||||
|
||||
self.remoteDogTimer setTimer( duration );
|
||||
println( "done setting hud timer" );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
RemoteDogWaitForTimeout( duration )
|
||||
{
|
||||
self endon( "cleanup_remote_dog" );
|
||||
wait duration;
|
||||
remoteDogDebugPrint( "RemoteDogWaitForTimeout() Time's up!" );
|
||||
self notify( "remote_dog_time_is_up" );
|
||||
self._time_is_up = 1;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
destroyRemoteDogTimer()
|
||||
{
|
||||
remoteDogDebugPrint( "cleanup timer!" );
|
||||
self.remoteDogTimer Destroy();
|
||||
}
|
||||
|
||||
/*
|
||||
QUAKED script_vehicle_nx_miniuav_player_mp (1 0 0) (-16 -16 -24) (16 16 32) USABLE SPAWNER
|
||||
|
||||
put this in your GSC:
|
||||
maps\mp\killstreaks\_miniuav::main( "nx_vehicle_miniuav" );
|
||||
|
||||
and these lines in your CSV:
|
||||
include,nx_vehicle_miniuav_player
|
||||
|
||||
defaultmdl="nx_vehicle_miniuav"
|
||||
default:"vehicletype" "nx_miniuav_player"
|
||||
default:"script_team" "allies"
|
||||
*/
|
461
maps/mp/killstreaks/_remotemissile.gsc
Normal file
461
maps/mp/killstreaks/_remotemissile.gsc
Normal file
@ -0,0 +1,461 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
mapname = getDvar( "mapname" );
|
||||
if ( mapname == "mp_suburbia" )
|
||||
{
|
||||
level._missileRemoteLaunchVert = 7000;
|
||||
level._missileRemoteLaunchHorz = 10000;
|
||||
level._missileRemoteLaunchTargetDist = 2000;
|
||||
}
|
||||
else if ( mapname == "mp_mainstreet" )
|
||||
{
|
||||
level._missileRemoteLaunchVert = 7000;
|
||||
level._missileRemoteLaunchHorz = 10000;
|
||||
level._missileRemoteLaunchTargetDist = 2000;
|
||||
}
|
||||
else
|
||||
{
|
||||
level._missileRemoteLaunchVert = 14000;
|
||||
level._missileRemoteLaunchHorz = 7000;
|
||||
level._missileRemoteLaunchTargetDist = 1500;
|
||||
|
||||
}
|
||||
precacheItem( "remotemissile_projectile_mp" );
|
||||
precacheShader( "ac130_overlay_grain" );
|
||||
precacheString( &"MP_CIVILIAN_AIR_TRAFFIC" );
|
||||
|
||||
level._rockets = [];
|
||||
|
||||
level._killstreakFuncs["predator_missile"] = ::tryUsePredatorMissile;
|
||||
level._killstreakFuncs["predator_marker"] = ::tryUsePredatorMarker;
|
||||
|
||||
level._missilesForSightTraces = [];
|
||||
}
|
||||
|
||||
tryUsePredatorMarker( lifeId )
|
||||
{
|
||||
|
||||
//okToUsePredatorMarker = true;
|
||||
//level endon( "game_ended" );
|
||||
//self endon( "death" );
|
||||
|
||||
|
||||
//println( "Got off" );
|
||||
//if (okToUsePredatorMarker == true)
|
||||
//{
|
||||
self usePredatorMarker();
|
||||
return true;
|
||||
//}
|
||||
//msg = self waittill_any_return( "pred_grenade_thrown" );
|
||||
|
||||
//if ( msg != "pred_grenade_thrown" )
|
||||
// self switchToOffhand( grenade );
|
||||
//return false;
|
||||
|
||||
}
|
||||
|
||||
usePredatorMarker()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
self endon("disconnect");
|
||||
|
||||
ognade = self GetCurrentOffhand();
|
||||
ognadeCount = self GetWeaponAmmoClip(ognade);
|
||||
|
||||
self SetWeaponAmmoClip( ognade, 0 );
|
||||
|
||||
self _giveWeapon("pred_grenade_mp");
|
||||
//println( "gave pred" );
|
||||
|
||||
self thread waitForPredatorMarker( ognade, ognadeCount );
|
||||
|
||||
|
||||
}
|
||||
|
||||
waitForPredatorMarker( nadeId, nadeCount){
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
self endon("disconnect");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
self waittill( "grenade_fire", grenade, weaponName );
|
||||
//println( weaponName );
|
||||
if( weaponName == "pred_grenade_mp" )
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (nadeCount > 0)
|
||||
{
|
||||
self _giveWeapon(nadeId);
|
||||
//println( "gave grenade back" );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
dontLosePredMarker()
|
||||
{
|
||||
self endon( "grenade_fire");
|
||||
|
||||
self waittill("death");
|
||||
println( "in dontLose FOR" );
|
||||
predNadeCheck = self GetCurrentOffhand();
|
||||
predNadeCount = self GetWeaponAmmoClip(predNadeCheck);
|
||||
if ( predNadeCheck != "pred_grenade_mp" && predNadeCount != 1 )
|
||||
{
|
||||
self SetWeaponAmmoClip( "pred_grenade_mp" , 1 );
|
||||
println( "not gonna lose it!" );
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
tryUsePredatorMissile( lifeId )
|
||||
{
|
||||
if ( isDefined( level._civilianJetFlyBy ) )
|
||||
{
|
||||
self iPrintLnBold( &"MP_CIVILIAN_AIR_TRAFFIC" );
|
||||
return false;
|
||||
}
|
||||
|
||||
self setUsingRemote( "remotemissile" );
|
||||
result = self maps\mp\killstreaks\_killstreaks::initRideKillstreak();
|
||||
if ( result != "success" )
|
||||
{
|
||||
if ( result != "disconnect" )
|
||||
self clearUsingRemote();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
level thread _fire( lifeId, self );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
getBestSpawnPoint( remoteMissileSpawnPoints )
|
||||
{
|
||||
validEnemies = [];
|
||||
|
||||
foreach ( spawnPoint in remoteMissileSpawnPoints )
|
||||
{
|
||||
spawnPoint.validPlayers = [];
|
||||
spawnPoint.spawnScore = 0;
|
||||
}
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( !isReallyAlive( player ) )
|
||||
continue;
|
||||
|
||||
if ( player.team == self.team )
|
||||
continue;
|
||||
|
||||
if ( player.team == "spectator" )
|
||||
continue;
|
||||
|
||||
bestDistance = 999999999;
|
||||
bestSpawnPoint = undefined;
|
||||
|
||||
foreach ( spawnPoint in remoteMissileSpawnPoints )
|
||||
{
|
||||
//could add a filtering component here but i dont know what it would be.
|
||||
spawnPoint.validPlayers[spawnPoint.validPlayers.size] = player;
|
||||
|
||||
potentialBestDistance = Distance2D( spawnPoint.targetent.origin, player.origin );
|
||||
|
||||
if ( potentialBestDistance <= bestDistance )
|
||||
{
|
||||
bestDistance = potentialBestDistance;
|
||||
bestSpawnpoint = spawnPoint;
|
||||
}
|
||||
}
|
||||
|
||||
assertEx( isDefined( bestSpawnPoint ), "Closest remote-missile spawnpoint undefined for player: " + player.name );
|
||||
bestSpawnPoint.spawnScore += 2;
|
||||
}
|
||||
|
||||
bestSpawn = remoteMissileSpawnPoints[0];
|
||||
foreach ( spawnPoint in remoteMissileSpawnPoints )
|
||||
{
|
||||
foreach ( player in spawnPoint.validPlayers )
|
||||
{
|
||||
spawnPoint.spawnScore += 1;
|
||||
|
||||
if ( bulletTracePassed( player.origin + (0,0,32), spawnPoint.origin, false, player ) )
|
||||
spawnPoint.spawnScore += 3;
|
||||
|
||||
if ( spawnPoint.spawnScore > bestSpawn.spawnScore )
|
||||
{
|
||||
bestSpawn = spawnPoint;
|
||||
}
|
||||
else if ( spawnPoint.spawnScore == bestSpawn.spawnScore ) // equal spawn weights so we toss a coin.
|
||||
{
|
||||
if ( coinToss() )
|
||||
bestSpawn = spawnPoint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ( bestSpawn );
|
||||
}
|
||||
|
||||
drawLine( start, end, timeSlice, color )
|
||||
{
|
||||
drawTime = int(timeSlice * 20);
|
||||
for( time = 0; time < drawTime; time++ )
|
||||
{
|
||||
line( start, end, color,false, 1 );
|
||||
wait ( 0.05 );
|
||||
}
|
||||
}
|
||||
_fire( lifeId, player )
|
||||
{
|
||||
remoteMissileSpawnArray = getEntArray( "remoteMissileSpawn" , "targetname" );
|
||||
//assertEX( remoteMissileSpawnArray.size > 0 && getMapCustom( "map" ) != "", "No remote missile spawn points found. Contact friendly neighborhood designer" );
|
||||
|
||||
foreach ( spawn in remoteMissileSpawnArray )
|
||||
{
|
||||
if ( isDefined( spawn.target ) )
|
||||
spawn.targetEnt = getEnt( spawn.target, "targetname" );
|
||||
}
|
||||
|
||||
if ( remoteMissileSpawnArray.size > 0 )
|
||||
remoteMissileSpawn = player getBestSpawnPoint( remoteMissileSpawnArray );
|
||||
else
|
||||
remoteMissileSpawn = undefined;
|
||||
|
||||
if ( isDefined( remoteMissileSpawn ) )
|
||||
{
|
||||
startPos = remoteMissileSpawn.origin;
|
||||
targetPos = remoteMissileSpawn.targetEnt.origin;
|
||||
|
||||
//thread drawLine( startPos, targetPos, 30, (0,1,0) );
|
||||
|
||||
vector = vectorNormalize( startPos - targetPos );
|
||||
startPos = vector_multiply( vector, 14000 ) + targetPos;
|
||||
|
||||
//thread drawLine( startPos, targetPos, 15, (1,0,0) );
|
||||
|
||||
rocket = MagicBullet( "remotemissile_projectile_mp", startpos, targetPos, player );
|
||||
}
|
||||
else
|
||||
{
|
||||
upVector = (0, 0, level._missileRemoteLaunchVert );
|
||||
backDist = level._missileRemoteLaunchHorz;
|
||||
targetDist = level._missileRemoteLaunchTargetDist;
|
||||
|
||||
forward = AnglesToForward( player.angles );
|
||||
startpos = player.origin + upVector + forward * backDist * -1;
|
||||
targetPos = player.origin + forward * targetDist;
|
||||
|
||||
rocket = MagicBullet( "remotemissile_projectile_mp", startpos, targetPos, player );
|
||||
}
|
||||
|
||||
if ( !IsDefined( rocket ) )
|
||||
{
|
||||
player clearUsingRemote();
|
||||
return;
|
||||
}
|
||||
|
||||
rocket thread maps\mp\gametypes\_weapons::AddMissileToSightTraces( player.team );
|
||||
|
||||
rocket thread handleDamage();
|
||||
|
||||
rocket.lifeId = lifeId;
|
||||
rocket.type = "remote";
|
||||
MissileEyes( player, rocket );
|
||||
}
|
||||
|
||||
/#
|
||||
_fire_noplayer( lifeId, player )
|
||||
{
|
||||
upVector = (0, 0, level._missileRemoteLaunchVert );
|
||||
backDist = level._missileRemoteLaunchHorz;
|
||||
targetDist = level._missileRemoteLaunchTargetDist;
|
||||
|
||||
forward = AnglesToForward( player.angles );
|
||||
startpos = player.origin + upVector + forward * backDist * -1;
|
||||
targetPos = player.origin + forward * targetDist;
|
||||
|
||||
rocket = MagicBullet( "remotemissile_projectile_mp", startpos, targetPos, player );
|
||||
|
||||
if ( !IsDefined( rocket ) )
|
||||
return;
|
||||
|
||||
rocket thread handleDamage();
|
||||
|
||||
rocket.lifeId = lifeId;
|
||||
rocket.type = "remote";
|
||||
|
||||
player CameraLinkTo( rocket, "tag_origin" );
|
||||
player ControlsLinkTo( rocket );
|
||||
|
||||
rocket thread Rocket_CleanupOnDeath();
|
||||
|
||||
wait ( 2.0 );
|
||||
|
||||
player ControlsUnlink();
|
||||
player CameraUnlink();
|
||||
}
|
||||
#/
|
||||
|
||||
handleDamage()
|
||||
{
|
||||
self endon ( "death" );
|
||||
self endon ( "deleted" );
|
||||
|
||||
self setCanDamage( true );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill( "damage" );
|
||||
|
||||
println ( "projectile damaged!" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MissileEyes( player, rocket )
|
||||
{
|
||||
//level endon ( "game_ended" );
|
||||
player endon ( "joined_team" );
|
||||
player endon ( "joined_spectators" );
|
||||
|
||||
rocket thread Rocket_CleanupOnDeath();
|
||||
player thread Player_CleanupOnGameEnded( rocket );
|
||||
player thread Player_CleanupOnTeamChange( rocket );
|
||||
|
||||
player VisionSetMissilecamForPlayer( "black_bw", 0 );
|
||||
|
||||
player endon ( "disconnect" );
|
||||
|
||||
if ( isDefined( rocket ) )
|
||||
{
|
||||
player VisionSetMissilecamForPlayer( game["thermal_vision"], 1.0 );
|
||||
player thread delayedFOFOverlay();
|
||||
player CameraLinkTo( rocket, "tag_origin" );
|
||||
player ControlsLinkTo( rocket );
|
||||
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
player setThirdPersonDOF( false );
|
||||
|
||||
rocket waittill( "death" );
|
||||
|
||||
// is defined check required because remote missile doesnt handle lifetime explosion gracefully
|
||||
// instantly deletes its self after an explode and death notify
|
||||
if ( isDefined(rocket) )
|
||||
player maps\mp\_matchdata::logKillstreakEvent( "predator_missile", rocket.origin );
|
||||
|
||||
player ControlsUnlink();
|
||||
player freezeControlsWrapper( true );
|
||||
|
||||
// If a player gets the final kill with a hellfire, level.gameEnded will already be true at this point
|
||||
if ( !level._gameEnded || isDefined( player.finalKill ) )
|
||||
player thread staticEffect( 0.5 );
|
||||
|
||||
wait ( 0.5 );
|
||||
|
||||
player ThermalVisionFOFOverlayOff();
|
||||
|
||||
player CameraUnlink();
|
||||
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
player setThirdPersonDOF( true );
|
||||
|
||||
}
|
||||
|
||||
player clearUsingRemote();
|
||||
}
|
||||
|
||||
|
||||
delayedFOFOverlay()
|
||||
{
|
||||
self endon ( "death" );
|
||||
self endon ( "disconnect" );
|
||||
level endon ( "game_ended" );
|
||||
|
||||
wait ( 0.15 );
|
||||
|
||||
self ThermalVisionFOFOverlayOn();
|
||||
}
|
||||
|
||||
staticEffect( duration )
|
||||
{
|
||||
self endon ( "disconnect" );
|
||||
|
||||
staticBG = newClientHudElem( self );
|
||||
staticBG.horzAlign = "fullscreen";
|
||||
staticBG.vertAlign = "fullscreen";
|
||||
staticBG setShader( "white", 640, 480 );
|
||||
staticBG.archive = true;
|
||||
staticBG.sort = 10;
|
||||
|
||||
static = newClientHudElem( self );
|
||||
static.horzAlign = "fullscreen";
|
||||
static.vertAlign = "fullscreen";
|
||||
static setShader( "ac130_overlay_grain", 640, 480 );
|
||||
static.archive = true;
|
||||
static.sort = 20;
|
||||
|
||||
wait ( duration );
|
||||
|
||||
static destroy();
|
||||
staticBG destroy();
|
||||
}
|
||||
|
||||
|
||||
Player_CleanupOnTeamChange( rocket )
|
||||
{
|
||||
rocket endon ( "death" );
|
||||
self endon ( "disconnect" );
|
||||
|
||||
self waittill_any( "joined_team" , "joined_spectators" );
|
||||
|
||||
if ( self.team != "spectator" )
|
||||
{
|
||||
self ThermalVisionFOFOverlayOff();
|
||||
self ControlsUnlink();
|
||||
self CameraUnlink();
|
||||
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( true );
|
||||
}
|
||||
self clearUsingRemote();
|
||||
|
||||
level._remoteMissileInProgress = undefined;
|
||||
}
|
||||
|
||||
|
||||
Rocket_CleanupOnDeath()
|
||||
{
|
||||
entityNumber = self getEntityNumber();
|
||||
level._rockets[ entityNumber ] = self;
|
||||
self waittill( "death" );
|
||||
|
||||
level._rockets[ entityNumber ] = undefined;
|
||||
}
|
||||
|
||||
|
||||
Player_CleanupOnGameEnded( rocket )
|
||||
{
|
||||
rocket endon ( "death" );
|
||||
self endon ( "death" );
|
||||
|
||||
level waittill ( "game_ended" );
|
||||
|
||||
self ThermalVisionFOFOverlayOff();
|
||||
self ControlsUnlink();
|
||||
self CameraUnlink();
|
||||
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( true );
|
||||
}
|
334
maps/mp/killstreaks/_rodsofgod.gsc
Normal file
334
maps/mp/killstreaks/_rodsofgod.gsc
Normal file
@ -0,0 +1,334 @@
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
precacheString( &"MP_LASE_TARGET_FOR_GUIDED_MORTAR" );
|
||||
precacheString( &"MP_WAIT_FOR_MORTAR_READY" );
|
||||
precacheString( &"MP_MORTAR_ROUNDS_DEPLETED" );
|
||||
|
||||
precacheItem( "remote_mortar_missile_mp" );
|
||||
PreCacheItem( "mortar_remote_mp" );
|
||||
|
||||
level._remote_mortar_fx["tracer"] = loadFx( "misc/tracer_incoming" );
|
||||
level._remote_mortar_fx["explosion"] = loadFx( "explosions/building_explosion_huge_gulag" );
|
||||
|
||||
level._effect[ "laserTarget" ] = loadfx("nx/misc/nx_laser_glow");
|
||||
level._killstreakFuncs["remote_mortar"] = ::tryUseRemoteMortar;
|
||||
|
||||
}
|
||||
|
||||
|
||||
tryUseRemoteMortar( lifeId )
|
||||
{
|
||||
if ( isDefined( self.lastStand ) && !self _hasPerk( "specialty_finalstand" ) )
|
||||
{
|
||||
self iPrintLnBold( &"MP_UNAVILABLE_IN_LASTSTAND" );
|
||||
return false;
|
||||
}
|
||||
|
||||
self setUsingRemote( "remote_mortar" );
|
||||
result = self maps\mp\killstreaks\_killstreaks::initRideKillstreak();
|
||||
if ( result != "success" )
|
||||
{
|
||||
if ( result != "disconnect" )
|
||||
self clearUsingRemote();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
self thread teamPlayerCardSplash( "used_remote_mortar", self );
|
||||
return startRemoteMortar( lifeId );
|
||||
}
|
||||
|
||||
|
||||
startRemoteMortar( lifeId )
|
||||
{
|
||||
remote = spawnRemote( lifeId, self );
|
||||
if ( !isDefined( remote ) )
|
||||
return false;
|
||||
|
||||
self thread linkRemoteTargeting( remote );
|
||||
|
||||
self maps\mp\_matchdata::logKillstreakEvent( "remote_mortar", self.origin );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
spawnRemote( lifeId, owner )
|
||||
{
|
||||
remote = spawnplane( owner, "script_model", level._UAVRig getTagOrigin( "tag_origin" ) );
|
||||
if ( !isDefined( remote ) )
|
||||
return undefined;
|
||||
|
||||
remote setModel( "vehicle_uav_static_mp" );
|
||||
remote thread maps\mp\killstreaks\_uav::damageTracker( false );
|
||||
remote.team = owner.team;
|
||||
remote.owner = owner;
|
||||
remote.lifeId = lifeId;
|
||||
remote.heliType = "remote_mortar";
|
||||
|
||||
remote thread maps\mp\killstreaks\_helicopter::heli_flares_monitor();
|
||||
|
||||
maps\mp\killstreaks\_uav::addUAVModel( remote );
|
||||
|
||||
// 3000, 4000, and 6500 are all average numbers pulled from the random ranges UAV uses
|
||||
// since the player's camera is linked to this vehicle, we want to control the location
|
||||
zOffset = 3000;
|
||||
angle = 0;
|
||||
radiusOffset = 4000;
|
||||
xOffset = cos( angle ) * radiusOffset;
|
||||
yOffset = sin( angle ) * radiusOffset;
|
||||
angleVector = vectorNormalize( (xOffset,yOffset,zOffset) );
|
||||
angleVector = ( angleVector * 6500 );
|
||||
|
||||
remote linkTo( level._UAVRig, "tag_origin", angleVector, (0,angle-90,0) );
|
||||
|
||||
remote thread handleDeath( owner );
|
||||
remote thread handleTimeout( owner );
|
||||
remote thread handleOwnerDisconnect( owner );
|
||||
|
||||
return remote;
|
||||
}
|
||||
|
||||
|
||||
showLazeMessage( remote, state, time )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon ( "disconnect" );
|
||||
remote endon ( "death" );
|
||||
self notify( "showing_laze_message" );
|
||||
self endon( "showing_laze_message" );
|
||||
|
||||
if ( isDefined( remote.msg ) )
|
||||
remote.msg destroyElem();
|
||||
|
||||
text = "";
|
||||
switch( state )
|
||||
{
|
||||
case "ready":
|
||||
text = &"MP_LASE_TARGET_FOR_GUIDED_MORTAR";
|
||||
color = (0.2, 1.0, 0.2);
|
||||
break;
|
||||
case "wait":
|
||||
text = &"MP_WAIT_FOR_MORTAR_READY";
|
||||
color = (0.8, 0.8, 0.2);
|
||||
break;
|
||||
case "done":
|
||||
text = &"MP_MORTAR_ROUNDS_DEPLETED";
|
||||
color = (1.0, 0.2, 0.2);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
remote.msg = self maps\mp\gametypes\_hud_util::createFontString( "objective", 1.5 );
|
||||
remote.msg maps\mp\gametypes\_hud_util::setPoint( "CENTER", "CENTER", 0 , 150 );
|
||||
remote.msg setText( text );
|
||||
remote.msg.color = color;
|
||||
|
||||
if ( !isDefined( time ) )
|
||||
time = 2.0;
|
||||
wait( time );
|
||||
|
||||
if ( isDefined( remote.msg ) )
|
||||
remote.msg destroyElem();
|
||||
}
|
||||
|
||||
|
||||
lookCenter()
|
||||
{
|
||||
wait( 0.05 );
|
||||
|
||||
lookVec = vectorToAngles( level._UAVRig.origin - self GetEye() );
|
||||
|
||||
self setPlayerAngles( lookVec );
|
||||
}
|
||||
|
||||
linkRemoteTargeting( remote )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "disconnect" );
|
||||
remote endon( "helicopter_done" );
|
||||
remote endon( "death" );
|
||||
|
||||
self VisionSetThermalForPlayer( game["thermal_vision"], 0 );
|
||||
self _giveWeapon("mortar_remote_mp");
|
||||
self SwitchToWeapon("mortar_remote_mp");
|
||||
self ThermalVisionOn();
|
||||
self ThermalVisionFOFOverlayOn();
|
||||
self thread maps\mp\killstreaks\_helicopter::thermalVision( remote );
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( false );
|
||||
|
||||
self PlayerLinkWeaponviewToDelta( remote, "tag_player", 1.0, 180, 180, 0, 180, true );
|
||||
self thread lookCenter();
|
||||
|
||||
remote thread maps\mp\killstreaks\_helicopter::heli_targeting();
|
||||
self thread maps\mp\killstreaks\_helicopter::weaponLockThink( remote );
|
||||
|
||||
// msg
|
||||
self thread showLazeMessage( remote, "ready", 5 );
|
||||
|
||||
// fire
|
||||
shotsFired = 0;
|
||||
while ( true )
|
||||
{
|
||||
if ( self attackButtonPressed() )
|
||||
{
|
||||
origin = self GetEye();
|
||||
forward = AnglesToForward( self GetPlayerAngles() );
|
||||
endpoint = origin + forward * 15000;
|
||||
|
||||
traceData = BulletTrace( origin, endpoint, true, self );
|
||||
if ( isDefined( traceData["position"] ) )
|
||||
{
|
||||
self playLocalSound( "stinger_locking" );
|
||||
self PlayRumbleOnEntity( "ac130_25mm_fire" );
|
||||
|
||||
remote.fxEnt = SpawnFx( level._effect[ "laserTarget" ], traceData["position"] );
|
||||
TriggerFx( remote.fxEnt );
|
||||
// wait ( 1.0 );
|
||||
self thread launchMortar( remote, traceData["position"] );
|
||||
|
||||
shotsFired++;
|
||||
if ( shotsFired < 3 )
|
||||
{
|
||||
self thread showLazeMessage( remote, "wait" );
|
||||
wait( 2.0 );
|
||||
remote.fxEnt delete();
|
||||
self thread showLazeMessage( remote, "ready" );
|
||||
}
|
||||
else
|
||||
{
|
||||
self thread showLazeMessage( remote, "wait" );
|
||||
wait( 2.0 );
|
||||
remote.fxEnt delete();
|
||||
self thread showLazeMessage( remote, "done" );
|
||||
wait( 2.0 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
wait( 0.05 );
|
||||
}
|
||||
else
|
||||
wait( 0.05 );
|
||||
}
|
||||
|
||||
self unlinkRemoteTargeting();
|
||||
remote thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
launchMortar( remote, pos )
|
||||
{
|
||||
PlayFx( level._remote_mortar_fx["tracer"], pos );
|
||||
thread playSoundinSpace( "fast_artillery_round", pos );
|
||||
|
||||
wait( 1 );
|
||||
|
||||
PlayFx( level._remote_mortar_fx["explosion"], pos );
|
||||
Earthquake( 1.0, 0.6, pos, 2000 );
|
||||
thread playSoundinSpace( "exp_suitcase_bomb_main", pos );
|
||||
physicsExplosionSphere( pos + (0,0,30), 250, 125, 2 );
|
||||
if ( isDefined( self ) )
|
||||
remote RadiusDamage( pos, 400, 200, 50, self, "MOD_EXPLOSIVE", "remote_mortar_missile_mp" );
|
||||
else
|
||||
remote RadiusDamage( pos, 400, 200, 50, undefined, "MOD_EXPLOSIVE", "remote_mortar_missile_mp" );
|
||||
}
|
||||
|
||||
|
||||
unlinkRemoteTargeting()
|
||||
{
|
||||
self RemoteCameraSoundscapeOff();
|
||||
self ThermalVisionOff();
|
||||
self ThermalVisionFOFOverlayOff();
|
||||
self unlink();
|
||||
self clearUsingRemote();
|
||||
if ( getDvarInt( "camera_thirdPerson" ) )
|
||||
self setThirdPersonDOF( true );
|
||||
self visionSetThermalForPlayer( game["thermal_vision"], 0 );
|
||||
|
||||
self switchToWeapon( self getLastWeapon() );
|
||||
weaponList = self GetWeaponsListExclusives();
|
||||
foreach ( weapon in weaponList )
|
||||
self takeWeapon( weapon );
|
||||
}
|
||||
|
||||
|
||||
handleTimeout( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
owner endon( "disconnect" );
|
||||
self endon( "death" );
|
||||
self endon( "helicopter_done" );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 45.0 );
|
||||
|
||||
if ( isDefined( owner ) )
|
||||
owner unlinkRemoteTargeting();
|
||||
self thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
handleDeath( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
owner endon( "disconnect" );
|
||||
self endon( "helicopter_done" );
|
||||
|
||||
self waittill( "death" );
|
||||
|
||||
owner unlinkRemoteTargeting();
|
||||
|
||||
forward = ( AnglesToRight( self.angles ) * 200 );
|
||||
playFx ( level._uav_fx[ "explode" ], self.origin, forward );
|
||||
|
||||
level thread removeRemote( self );
|
||||
self notify( "helicopter_done" );
|
||||
}
|
||||
|
||||
|
||||
handleOwnerDisconnect( owner )
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
owner endon( "death" );
|
||||
self endon( "death" );
|
||||
|
||||
owner waittill( "disconnect" );
|
||||
|
||||
self thread remoteLeave();
|
||||
}
|
||||
|
||||
|
||||
removeRemote( remote )
|
||||
{
|
||||
if ( isDefined( remote.msg ) )
|
||||
remote.msg destroyElem();
|
||||
if ( isDefined( remote.fxEnt ) )
|
||||
remote.fxEnt delete();
|
||||
remote delete();
|
||||
maps\mp\killstreaks\_uav::removeUAVModel( remote );
|
||||
}
|
||||
|
||||
|
||||
remoteLeave()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
|
||||
self notify( "helicopter_done" );
|
||||
self unlink();
|
||||
|
||||
destPoint = self.origin + ( AnglesToForward( self.angles ) * 20000 );
|
||||
self moveTo( destPoint, 60 );
|
||||
PlayFXOnTag( level._effect[ "ac130_engineeffect" ] , self, "tag_origin" );
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 3 );
|
||||
|
||||
self moveTo( destPoint, 4, 4, 0.0 );
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 4 );
|
||||
|
||||
level thread removeRemote( self );
|
||||
}
|
816
maps/mp/killstreaks/_spider.gsc
Normal file
816
maps/mp/killstreaks/_spider.gsc
Normal file
@ -0,0 +1,816 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
//****************************************************************************
|
||||
// **
|
||||
// Confidential - (C) Activision Publishing, Inc. 2010 **
|
||||
// **
|
||||
//****************************************************************************
|
||||
// **
|
||||
// Module: Prototype killstreak - Roboturret **
|
||||
// Once the killstreak is deployed, it will follow the player **
|
||||
// around the map and kill enemies. **
|
||||
// **
|
||||
// Created: May 31th, 2011 - James Chen **
|
||||
// **
|
||||
//***************************************************************************/
|
||||
|
||||
//tagJC<NOTE>: The current implementation consists of three components: one very small joint as vehicle serving as the connecting
|
||||
// base for the turret and the legs.
|
||||
//tagJC<TODO>: Known Issues (bugs)
|
||||
// (1) The animation for the turret is controlled by the another underlying (turret) script. Currently, the turret
|
||||
// does not play the proper animation when tracking/shooting enemies.
|
||||
// (2) The robo legs is 90 degree from the correct orientation of the vehicle.
|
||||
//tagJC<TODO>: Determine a better pathing logic under the current vehicle pathing limitation so the roboturret can really follow
|
||||
// the players around the level.
|
||||
|
||||
init()
|
||||
{
|
||||
//tagJC<NOTE>: Precache all the assets needed.
|
||||
//tagJC<NOTE>: nx_vehicle_roboturret_legs_vehicle is a very small joint which has all the required TAG for a vehicle.
|
||||
// It is used so the robo legs and the roboturrets can be attached to it and the game will handle it properly
|
||||
// according to the default vehicle animation.
|
||||
PrecacheVehicle( "proto_nx_vehicle_roboturret_legs_vehicle" );
|
||||
precacheModel( "nx_vehicle_roboturret_legs_vehicle" );
|
||||
|
||||
//tagJC<NOTE>: nx_vehicle_spider is the robo legs.
|
||||
PrecacheVehicle( "nx_spider_mp" );
|
||||
precacheModel( "nx_vehicle_spider" );
|
||||
|
||||
//tagJC<NOTE>: nx_ugv_robo_turret is the robo turret.
|
||||
precacheTurret( "ugv_robo_turret_mp" );
|
||||
precacheModel( "nx_ugv_robo_turret" );
|
||||
|
||||
//tagJC<NOTE>: These are the animations for the robo legs.
|
||||
precacheMpAnim( "nx_vh_roboturret_run" );
|
||||
precacheMpAnim( "nx_vh_roboturret_walk" );
|
||||
precacheMpAnim( "nx_vh_roboturret_idle" );
|
||||
|
||||
//level._spiderSpawners = Vehicle_GetSpawnerArray();
|
||||
|
||||
//tagJC<NOTE>: This is the killstreak activation callback for the roboturret.
|
||||
level._killstreakFuncs["spider"] = ::try_use_killstreak;
|
||||
|
||||
//tagJC<NOTE>: Use this script to update/initialize players as they connect to the game.
|
||||
level thread onPlayerConnect();
|
||||
|
||||
//tagJC<NOTE>: In order for the roboturret to work correctly, the level needs to have at least one "spidernode".
|
||||
level._spiderNodes = getVehicleNodeArray( "spidernode", "script_noteworthy" );
|
||||
StartNodeMappingTable();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Checking whether the level is properly set up for the roboturret killstreak.
|
||||
try_use_killstreak( lifeId )
|
||||
{
|
||||
if ( ! level._spiderNodes.size )
|
||||
{
|
||||
self iPrintLnBold( "Spider is currently not supported in this level, bug your friendly neighborhood Level Designer, Failed to locate valid spider node." );
|
||||
return false;
|
||||
}
|
||||
|
||||
//tagJC<NOTE>: Test script of which any desired testing can be performed before integrated into working prototype.
|
||||
//testscript();
|
||||
|
||||
killstreak_template_use( lifeId );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: This function creates a mapping table for all the start nodes. It uses the coordinate of the start node as the
|
||||
// the index for the first dimension of the array. The second dimension of the array stores all the start nodes that
|
||||
// the current start node can travel to.
|
||||
StartNodeMappingTable()
|
||||
{
|
||||
println( "StartNodeMappingTable" );
|
||||
level._StartNodeMapping = [];
|
||||
println( "################################" );
|
||||
for ( i = 0; i < level._spiderNodes.size; i++ )
|
||||
{
|
||||
StartNode = level._spiderNodes[i];
|
||||
//tagJC<NOTE>: Getting the end node of the path whose start node is StartNode
|
||||
EndNode = GetVehicleNode( StartNode.target, "targetname" );
|
||||
//tagJC<NOTE>: Creating the index using the StartNode's coordinate
|
||||
index = "X" + StartNode.origin[0] + "Y" + StartNode.origin[1] + "Z" + StartNode.origin[2];
|
||||
println( "The index is " + index );
|
||||
for ( j = 0; j < level._spiderNodes.size; j++ )
|
||||
{
|
||||
TargetStartNode = level._spiderNodes[j];
|
||||
//tagJC<NOTE>: Store the TargetStartNode into the array if its distance is less than 250 units from the EndNode
|
||||
if ( distance( EndNode.origin, TargetStartNode.origin ) < 250 )
|
||||
{
|
||||
if ( ! IsDefined (level._StartNodeMapping[index]) )
|
||||
{
|
||||
level._StartNodeMapping[index][0] = TargetStartNode;
|
||||
}
|
||||
else
|
||||
{
|
||||
ArraySize = level._StartNodeMapping[index].size;
|
||||
level._StartNodeMapping[index][ArraySize] = TargetStartNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
//tagJC<NOTE>: Debugging output to look at the array
|
||||
println( "There are " + level._StartNodeMapping[index].size + " startnodes connected" );
|
||||
for ( r = 0; r < level._StartNodeMapping[index].size; r++)
|
||||
{
|
||||
println( " The coordinate is " + level._StartNodeMapping[index][r].origin );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Test script for any desired functionality, such as loading model, playing certain animation etc..
|
||||
// This is to make sure things are working properly before they are integrated into the working prototype.
|
||||
testscript()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
// tagJC<NOTE>: This is the callback that executes when the killstreak is activated by a player pressing on the dpad.
|
||||
killstreak_template_use( lifeId )
|
||||
{
|
||||
assert( isDefined( self ) );
|
||||
|
||||
//tagJC<NOTE>: spawning the small joint as the vehicle and setting the associated attributes.
|
||||
level._spider = spawnVehicle( "nx_vehicle_roboturret_legs_vehicle", "roboturret", "proto_nx_vehicle_roboturret_legs_vehicle", (0, 0, 0), (0, 0, 0) );
|
||||
level._spider.health = 3000;
|
||||
level._spider.targeting_delay = 1;
|
||||
level._spider.team = self.team;
|
||||
level._spider.pers["team"] = level._spider.team;
|
||||
level._spider.owner = self;
|
||||
level._spider setCanDamage( true );
|
||||
level._spider.standardSpeed = 10;
|
||||
level._spider.evadeSpeed = 50;
|
||||
level._spider.dangerSpeed = 15;
|
||||
level._spider.miniEngagementSpeed = 15;
|
||||
level._spider.engagementSpeed = 15;
|
||||
//tagJC<NOTE>: Kill the vehicle if it is dropped for more than 2048 units
|
||||
level._spider thread deleteOnZ();
|
||||
|
||||
//tagJC<NOTE>: Spawning the robo legs
|
||||
spiderScriptModel = spawn ( "script_model", level._spider.origin );
|
||||
spiderScriptModel setModel ( "nx_vehicle_spider" );
|
||||
spiderScriptModel ScriptModelPlayAnim ( "nx_vh_roboturret_idle" );
|
||||
level._spiderCurrentAnimation = "nx_vh_roboturret_idle";
|
||||
//tagJC<NOTE>: Linking the robo legs to the vehicle.
|
||||
spiderScriptModel linkTo ( level._spider, "TAG_ORIGIN" , (0, 0, 0), (0, 0, 0) );
|
||||
spiderScriptModel thread loopOnLegs ( level._spider );
|
||||
|
||||
//tagJC<NOTE>: Spawning the roboturret and setting its attributes.
|
||||
spiderTurret = spawnTurret( "misc_turret", level._spider.origin, "ugv_main_turret_mp" );
|
||||
//tagJC<NOTE>: Linking the turret to the scripted robo legs model.
|
||||
spiderTurret linkTo( spiderScriptModel, "TAG_TURRET", (0,0,0), (0,0,0) );
|
||||
spiderTurret setModel( "nx_ugv_robo_turret" );
|
||||
spiderTurret.angles = level._spider.angles;
|
||||
spiderTurret.owner = level._spider.owner;
|
||||
spiderTurret makeTurretInoperable();
|
||||
level._spider.mgTurret = spiderTurret;
|
||||
level._spider.mgTurret SetDefaultDropPitch( 0 );
|
||||
//tagJC<NOTE>: Start the turret to track and shoot enemies.
|
||||
level._spider thread tankGetMiniTargets();
|
||||
|
||||
//tagJC<NOTE>: Finding the spider start node that is closest to the player.
|
||||
closest_spidernode = find_closest_spidernode( self, level._spiderNodes );
|
||||
|
||||
//tagJC<NOTE>: Start moving the roboturret according to player's position.
|
||||
level._spider thread move_spider ( self, closest_spidernode );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: There are three animations that the robo legs can play: idel, walk and run
|
||||
loopOnLegs ( vehicle )
|
||||
{
|
||||
timer = 0;
|
||||
while ( 1 )
|
||||
{
|
||||
self.angle = vehicle.angle;
|
||||
speed = vehicle Vehicle_GetSpeed();
|
||||
|
||||
//tagJC<NOTE>: If the vehicle speed is faster than 10 MPH, the legs will run
|
||||
if ( speed > 10 )
|
||||
{
|
||||
timer = 0;
|
||||
if ( level._spiderCurrentAnimation != "nx_vh_roboturret_run" )
|
||||
{
|
||||
self ScriptModelPlayAnim ( "nx_vh_roboturret_run" );
|
||||
level._spiderCurrentAnimation = "nx_vh_roboturret_run";
|
||||
self stoploopsound("robot_sentry_walk");
|
||||
self playloopsound("robot_sentry_run");
|
||||
}
|
||||
}
|
||||
//tagJC<NOTE>: If the vehicle speed is between 10 and 0 MPH, the legs will walk
|
||||
else if ( speed < 10 && speed > 0 )
|
||||
{
|
||||
timer = 0;
|
||||
if ( level._spiderCurrentAnimation != "nx_vh_roboturret_walk" )
|
||||
{
|
||||
self ScriptModelPlayAnim ( "nx_vh_roboturret_walk" );
|
||||
level._spiderCurrentAnimation = "nx_vh_roboturret_walk";
|
||||
self stoploopsound("robot_sentry_run");
|
||||
self playloopsound("robot_sentry_walk");
|
||||
}
|
||||
}
|
||||
//tagJC<NOTE>: If the vehicle speed is 0 MPH, the legs will be idel
|
||||
else
|
||||
{
|
||||
timer = timer + 1;
|
||||
//tagJC<NOTE>: If the roboturret has been idle for 15 seconds
|
||||
if ( timer == 30 )
|
||||
{
|
||||
vehicle playsound ( "roboturret_idle_vo" );
|
||||
//vehicle playsound ( "roboturret_kill_vo" );
|
||||
timer = 0;
|
||||
}
|
||||
if ( level._spiderCurrentAnimation != "nx_vh_roboturret_idle" )
|
||||
{
|
||||
self stoploopsound("robot_sentry_run");
|
||||
self stoploopsound("robot_sentry_walk");
|
||||
self ScriptModelPlayAnim ( "nx_vh_roboturret_idle" );
|
||||
level._spiderCurrentAnimation = "nx_vh_roboturret_idle";
|
||||
}
|
||||
}
|
||||
println ( "timer is: " + timer );
|
||||
wait ( 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Currently, in order for this implementation to work, designers would have to place many pairs of bi-directional vehicle nodes
|
||||
// in the level. Given the limitation that vehicle seems to be only moving when it is on a vehicle path, the roboturret
|
||||
// cannot quite follow the players perfectly yet. Players would have to get close to the roboturret and then guide
|
||||
// it to a different position.
|
||||
move_spider ( owner, startNode )
|
||||
{
|
||||
//self playsound( "roboturret_deploy_vo" );
|
||||
self Vehicle_SetSpeed( 30, 5, 5 );
|
||||
//tagJC<NOTE>: Starting the roboturret along the path where its starting node is the roboturret's spawning node
|
||||
self AttachPath( startNode );
|
||||
self StartPath( startNode );
|
||||
self waittill( "reached_end_node" );
|
||||
self playsound( "roboturret_deploy_vo" );
|
||||
|
||||
prev_node = startNode;
|
||||
while ( 1 )
|
||||
{
|
||||
index = "X" + prev_node.origin[0] + "Y" + prev_node.origin[1] + "Z" + prev_node.origin[2];
|
||||
best_node = find_best_spidernode( owner, level._StartNodeMapping[index] );
|
||||
//if ( distance ( owner.origin, level._spider.origin ) > 50 )
|
||||
if ( isGettingCloserToPlayer ( owner, best_node ) )
|
||||
{
|
||||
//if ( prev_node != best_node )
|
||||
//{
|
||||
self StartPath( best_node );
|
||||
self waittill( "reached_end_node" );
|
||||
prev_node = best_node;
|
||||
//println( "This is after subsequent reached_end_node" );
|
||||
//}
|
||||
}
|
||||
else
|
||||
{
|
||||
wait 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: This function checks whether the turret will be moving away from the player or not
|
||||
isGettingCloserToPlayer ( owner, StartNode )
|
||||
{
|
||||
EndNode = GetVehicleNode( StartNode.target, "targetname" );
|
||||
if ( distance ( owner.origin, EndNode.origin ) > distance ( owner.origin, StartNode.origin ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: From the ReachableNodeList, determine the node that is will lead the turret to the player
|
||||
find_best_spidernode( owner, ReachableNodeList )
|
||||
{
|
||||
target_vector = VectorNormalize ( owner.origin - level._spider.origin );
|
||||
//tagJC<NOTE>: Creating an arbitrary base line using the first node in the node awway
|
||||
best_node = ReachableNodeList [0];
|
||||
best_dot_product = VectorDot ( VectorNormalize( best_node.origin - level._spider.origin ), target_vector );
|
||||
for ( i = 1; i < ReachableNodeList.size; i++)
|
||||
{
|
||||
//tagJC<NOTE>: If another node in the list can produce a larger dot product, that node is the best node
|
||||
dot_product = VectorDot ( VectorNormalize( ReachableNodeList[i].origin - level._spider.origin ), target_vector );
|
||||
if ( dot_product > best_dot_product )
|
||||
{
|
||||
best_node = ReachableNodeList[i];
|
||||
}
|
||||
}
|
||||
return best_node;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
tankGetMiniTargets()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "leaving" );
|
||||
miniTargets = [];
|
||||
println( "Geting Mini Targets" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
miniTargets = [];
|
||||
players = level._players;
|
||||
|
||||
//tagJC<NOTE>: Putting all the players on the oppositing team into a array.
|
||||
for (i = 0; i <= players.size; i++)
|
||||
{
|
||||
if ( isMiniTarget( players[i] ) )
|
||||
{
|
||||
if( isdefined( players[i] ) )
|
||||
miniTargets[miniTargets.size] = players[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
wait( .05 );
|
||||
}
|
||||
//tagJC<NOTE>: If there is at least one enemy, start acquiring the target
|
||||
if ( miniTargets.size > 0 )
|
||||
{
|
||||
self acquireMiniTarget( miniTargets );
|
||||
return;
|
||||
}
|
||||
else
|
||||
wait( 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: From the potential target list, determine whether there is any target that is feasible/practical for the turret
|
||||
// to target.
|
||||
isMiniTarget( potentialTarget )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
if ( !isalive( potentialTarget ) || potentialTarget.sessionstate != "playing" )
|
||||
return false;
|
||||
|
||||
if ( !isdefined( potentialTarget.pers["team"] ) )
|
||||
return false;
|
||||
|
||||
if ( potentialTarget == self.owner )
|
||||
return false;
|
||||
|
||||
if ( distanceSquared( potentialTarget.origin , self.origin ) > 1024*1024 )
|
||||
return false;
|
||||
|
||||
if ( level._teamBased && potentialTarget.pers["team"] == self.team )
|
||||
return false;
|
||||
|
||||
if ( potentialTarget.pers["team"] == "spectator" )
|
||||
return false;
|
||||
|
||||
if ( isdefined( potentialTarget.spawntime ) && ( gettime() - potentialTarget.spawntime )/1000 <= 5 )
|
||||
return false;
|
||||
|
||||
if ( isDefined( self ) )
|
||||
{
|
||||
minTurretEye = self.mgTurret.origin + ( 0, 0, 64 );
|
||||
minTurretCanSeeTarget = potentialTarget sightConeTrace( minTurretEye, self );
|
||||
|
||||
if ( minTurretCanSeeTarget < 1 )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: From the target list, determine which one is the best target and shoot it.
|
||||
acquireMiniTarget( targets )
|
||||
{
|
||||
self endon( "death" );
|
||||
|
||||
//tagJC<NOTE>: If there is only one target in the list, it is the best target.
|
||||
if ( targets.size == 1 )
|
||||
{
|
||||
self.bestMiniTarget = targets[0];
|
||||
}
|
||||
//tagJC<NOTE>: Else, determine the best target in the list.
|
||||
else
|
||||
{
|
||||
self.bestMiniTarget = self getBestMiniTarget( targets );
|
||||
}
|
||||
|
||||
self notify( "acquiringMiniTarget" );
|
||||
//tagJC<NOTE>: Set turret to target the best target.
|
||||
self.mgTurret SetTargetEntity( self.bestMiniTarget, ( 0,0,42 ) );
|
||||
wait( .15 );
|
||||
//tagJC<NOTE>: Set turret to fire at the best target.
|
||||
self thread fireMiniOnTarget();
|
||||
//tagJC<NOTE>: Abandon the target when it is killed.
|
||||
self thread watchMiniTargetDeath( targets );
|
||||
self thread watchMiniTargetDistance( targets );
|
||||
self thread watchMiniTargetThreat( self.bestMiniTarget );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Determine the best target from the target list
|
||||
getBestMiniTarget( targets )
|
||||
{
|
||||
self endon( "death" );
|
||||
tankOrigin = self.origin;
|
||||
|
||||
closest = undefined;
|
||||
bestTarget = undefined;
|
||||
|
||||
foreach ( targ in targets )
|
||||
{
|
||||
curDist = Distance( self.origin, targ.origin );
|
||||
|
||||
//tagJC<NOTE>: If the target is holding or using explosives, push the target to a higher priority
|
||||
curWeaon = targ GetCurrentWeapon();
|
||||
if ( isSubStr( curWeaon, "at4" ) || isSubStr( curWeaon, "jav" ) || isSubStr( curWeaon, "c4" ) || isSubStr( curWeaon, "smart" ) || isSubStr( curWeaon, "grenade" ) )
|
||||
{
|
||||
curDist -= 200;
|
||||
}
|
||||
if ( !isDefined( closest ) )
|
||||
{
|
||||
closest = curDist;
|
||||
bestTarget = targ;
|
||||
}
|
||||
else if ( closest > curDist )
|
||||
{
|
||||
closest = curDist;
|
||||
bestTarget = targ;
|
||||
}
|
||||
}
|
||||
return ( bestTarget );
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Firing the turret at the target.
|
||||
fireMiniOnTarget()
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "abandonedMiniTarget" );
|
||||
self endon( "killedMiniTarget" );
|
||||
noTargTime = undefined;
|
||||
miniAcquiredTime = getTime();
|
||||
|
||||
if ( !isDefined( self.bestMiniTarget ) )
|
||||
{
|
||||
println( "No Targ to fire on" );
|
||||
return;
|
||||
}
|
||||
|
||||
println( "firing at best target" );
|
||||
|
||||
while( 1 )
|
||||
{
|
||||
if ( !isDefined ( self.mgTurret getTurretTarget( true ) ) )
|
||||
{
|
||||
if ( !isDefined( noTargTime ) )
|
||||
{
|
||||
noTargTime = getTime();
|
||||
}
|
||||
|
||||
curTime = getTime();
|
||||
|
||||
//tagJC<NOTE>: If there has been more than 1 milliseconds without a target, abandon the target.
|
||||
if ( noTargTime - curTime > 1 )
|
||||
{
|
||||
noTargTime = undefined;
|
||||
self thread explicitAbandonMiniTarget();
|
||||
return;
|
||||
}
|
||||
println("Waiting because the turret doesnt have a target" );
|
||||
wait ( .5 );
|
||||
continue;
|
||||
}
|
||||
//tagJC<NOTE>: Firing a random number of shots between 2 to 6.
|
||||
numShots = randomIntRange( 2, 6 );
|
||||
for ( i = 0; i < numShots; i++ )
|
||||
{
|
||||
println( "actually shooting turret" );
|
||||
self.mgTurret ShootTurret();
|
||||
wait ( .25 );
|
||||
}
|
||||
wait ( randomFloatRange( 0.05, 0.1 ) );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Clearing the current target list for the turret and starting to get more targets.
|
||||
explicitAbandonMiniTarget( noNewTarget )
|
||||
{
|
||||
self notify( "abandonedMiniTarget" );
|
||||
println( "ABANDONED MINI TARGET" );
|
||||
|
||||
self.bestMiniTarget = undefined;
|
||||
self.mgTurret ClearTargetEntity();
|
||||
|
||||
if ( isDefined(noNewTarget) && noNewTarget )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self thread tankGetMiniTargets();
|
||||
return;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Wait for the target's death. Once the target is killed, clear the target list and get more targets.
|
||||
watchMiniTargetDeath( targets )
|
||||
{
|
||||
self endon( "abandonedMiniTarget" );
|
||||
self endon( "death" );
|
||||
if ( ! isDefined( self.bestMiniTarget ) )
|
||||
return;
|
||||
|
||||
self.bestMiniTarget waittill( "death" );
|
||||
//self playsound ( "roboturret_idle_vo" );
|
||||
self playsound ( "roboturret_kill_vo" );
|
||||
|
||||
self notify( "killedMiniTarget" );
|
||||
println( "Killed Mini Target" );
|
||||
|
||||
self.bestMiniTarget = undefined;
|
||||
self.mgTurret ClearTargetEntity();
|
||||
self tankGetMiniTargets();
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: If the target is more than 1024 units away, abandon the target
|
||||
watchMiniTargetDistance( targets )
|
||||
{
|
||||
self endon( "abandonedMiniTarget" );
|
||||
self endon( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if (! isDefined( self.bestMiniTarget ) )
|
||||
return;
|
||||
|
||||
trace = BulletTrace( self.mgTurret.origin, self.bestMiniTarget.origin, false, self );
|
||||
traceDistance = Distance(self.origin, trace["position"] );
|
||||
|
||||
if ( traceDistance > 1024 )
|
||||
{
|
||||
println( "MINI TARGET DIST TOO FAR!!!" );
|
||||
self thread explicitAbandonMiniTarget();
|
||||
return;
|
||||
}
|
||||
println( traceDistance );
|
||||
wait ( 2 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: If there is a target that is closer to the current target, abandon the curret target
|
||||
watchMiniTargetThreat( curTarget )
|
||||
{
|
||||
self endon( "abandonedMiniTarget" );
|
||||
self endon( "death" );
|
||||
self endon( "killedMiniTarget" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
miniTargets = [];
|
||||
players = level._players;
|
||||
|
||||
for (i = 0; i <= players.size; i++)
|
||||
{
|
||||
if ( isMiniTarget( players[i] ) )
|
||||
{
|
||||
if( !isdefined( players[i] ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( !isdefined(curTarget) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
traceOldTarg = Distance(self.origin, CurTarget.origin );
|
||||
traceNewTarg = Distance(self.origin, players[i].origin );
|
||||
|
||||
if ( traceNewTarg < traceOldTarg )
|
||||
{
|
||||
self thread explicitAbandonMiniTarget();
|
||||
return;
|
||||
}
|
||||
}
|
||||
wait( .05 );
|
||||
}
|
||||
wait( .25 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: From the entity_list, return the one that is closest to the entity
|
||||
find_closest_spidernode ( target, entity_list )
|
||||
{
|
||||
//tagJC<NOTE>: Use an arbitrary distance as the base for comparision
|
||||
closest_distance = distance( target.origin , entity_list[0].origin );
|
||||
closest_entity = entity_list[0];
|
||||
for ( i = 1; i < entity_list.size; i++ )
|
||||
{
|
||||
//tagJC<NOTE>: If another entity on the list results in a shorter distance, update the results accordingly
|
||||
if ( distance( target.origin , entity_list[i].origin ) < closest_distance )
|
||||
{
|
||||
closest_distance = distance( target.origin , entity_list[i].origin );
|
||||
closest_entity = entity_list[i];
|
||||
}
|
||||
}
|
||||
return closest_entity;
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: If a vehicle is dropped more than 2048 units, kill it.
|
||||
deleteOnZ()
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
originalZ = self.origin[2];
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
if ( originalZ - self.origin[2] > 2048 )
|
||||
{
|
||||
self.health = 0;
|
||||
self notify( "death" );
|
||||
return;
|
||||
}
|
||||
wait ( 1.0 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: This function tracks player's movement and put the closest node to the player into a queue
|
||||
TrackingPlayers( owner )
|
||||
{
|
||||
self.PlayerLocations = [];
|
||||
while ( 1 )
|
||||
{
|
||||
close_node = find_closest_spidernode( owner, level._spiderNodes );
|
||||
if ( self.PlayerLocations.size == 0 )
|
||||
{
|
||||
self.PlayerLocations[0] = close_node;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = self.PlayerLocations.size;
|
||||
Player_last_location = self.PlayerLocations[ size - 1 ];
|
||||
if ( close_node != Player_last_location )
|
||||
{
|
||||
self.PlayerLocations[ size ] = close_node;
|
||||
//println ( "========== This is inside Tracking Player ============" );
|
||||
//println ( "The location of the node being added is: " + self.PlayerLocations[ size ].origin);
|
||||
//println ( "The size of PlayerLocations is: " + self.PlayerLocations.size );
|
||||
//println ( "======================================================" );
|
||||
}
|
||||
}
|
||||
wait( 0.5 );
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
//tagJC<NOTE>: Remove the first item in the list by shifting entities in the list forward by one slot in the list
|
||||
RemoveFirstItem ( list )
|
||||
{
|
||||
if ( list.size > 0 )
|
||||
{
|
||||
for ( i = 0 ; i < list.size - 1 ; i ++ )
|
||||
{
|
||||
list[ i ] = list[ i + 1 ];
|
||||
}
|
||||
list[ list.size - 1 ] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
// tagJC<NOTE>: This script is running on the global level object, it monitors players connecting to the game.
|
||||
// Its main purpose is to apply the onPlayerSpawned script to each player as they connect to the game.
|
||||
onPlayerConnect()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
level waittill("connected", player);
|
||||
player thread onPlayerSpawned();
|
||||
}
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
// tagJC<NOTE>: This script is running on each player in the game, it recieves a notification each time the player it is running on spawns in the game
|
||||
// Its main purpose is to initialize any per player data, as well as update the player subject to any global killstreak data when that player spawns.
|
||||
onPlayerSpawned()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
println( "player spwaned" );
|
||||
|
||||
// init/manage any per player killstreak data here
|
||||
}
|
||||
}
|
||||
|
||||
main ( vehicle, model )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//*******************************************************************
|
||||
// *
|
||||
// *
|
||||
//*******************************************************************
|
||||
|
||||
/*
|
||||
QUAKED script_vehicle_nx_proto_roboturret (1 0 0) (-16 -16 -24) (16 16 32) USABLE SPAWNER
|
||||
|
||||
maps\mp\killstreaks\_spider::main( "nx_vehicle_roboturret_legs_vehicle", "proto_nx_vehicle_roboturret_legs_vehicle" );
|
||||
|
||||
include,prototype_nx_vehicle_roboturret
|
||||
|
||||
defaultmdl="nx_vehicle_roboturret_legs_vehicle"
|
||||
default:"vehicletype" "proto_nx_vehicle_roboturret_legs_vehicle"
|
||||
default:"script_team" "allies"
|
||||
*/
|
2697
maps/mp/killstreaks/_tank.gsc
Normal file
2697
maps/mp/killstreaks/_tank.gsc
Normal file
File diff suppressed because it is too large
Load Diff
881
maps/mp/killstreaks/_uav.gsc
Normal file
881
maps/mp/killstreaks/_uav.gsc
Normal file
@ -0,0 +1,881 @@
|
||||
#include maps\mp\_utility;
|
||||
#include maps\mp\gametypes\_hud_util;
|
||||
#include common_scripts\utility;
|
||||
|
||||
init()
|
||||
{
|
||||
precacheString( &"MP_WAR_RADAR_ACQUIRED" );
|
||||
precacheString( &"MP_WAR_RADAR_ACQUIRED_ENEMY" );
|
||||
precacheString( &"MP_WAR_RADAR_EXPIRED" );
|
||||
precacheString( &"MP_WAR_RADAR_EXPIRED_ENEMY" );
|
||||
|
||||
precacheString( &"MP_WAR_COUNTER_RADAR_ACQUIRED" );
|
||||
precacheString( &"MP_WAR_COUNTER_RADAR_ACQUIRED_ENEMY" );
|
||||
precacheString( &"MP_WAR_COUNTER_RADAR_EXPIRED" );
|
||||
precacheString( &"MP_WAR_COUNTER_RADAR_EXPIRED_ENEMY" );
|
||||
|
||||
precacheString( &"MP_LASE_TARGET_FOR_PREDATOR_STRIKE" );
|
||||
|
||||
precacheModel( "vehicle_uav_static_mp" );
|
||||
|
||||
precacheItem( "uavstrikebinoculars_mp" );
|
||||
precacheItem( "uav_strike_projectile_mp" );
|
||||
|
||||
level._radarViewTime = 30; // time radar remains active
|
||||
level._uavBlockTime = 30; // this only seems to be used for the FFA version.
|
||||
|
||||
assert( level._radarViewTime > 7 );
|
||||
assert( level._uavBlockTime > 7 );
|
||||
|
||||
level._uav_fx[ "explode" ] = loadFx( "explosions/helicopter_explosion_cobra_low" );
|
||||
|
||||
level._killStreakFuncs["uav"] = ::tryUseUAV;
|
||||
level._killStreakFuncs["double_uav"] = ::tryUseDoubleUAV;
|
||||
level._killStreakFuncs["counter_uav"] = ::tryUseCounterUAV;
|
||||
level._killstreakFuncs["uav_strike"] = ::tryUseUAVStrike;
|
||||
level._killstreakSetupFuncs["uav_strike"] = ::UAVStrikeSetup;
|
||||
|
||||
level._effect[ "laserTarget" ] = loadfx("nx/misc/nx_laser_glow");
|
||||
|
||||
minimapOrigins = getEntArray( "minimap_corner", "targetname" );
|
||||
if ( miniMapOrigins.size )
|
||||
uavOrigin = maps\mp\gametypes\_spawnlogic::findBoxCenter( miniMapOrigins[0].origin, miniMapOrigins[1].origin );
|
||||
else
|
||||
uavOrigin = (0,0,0);
|
||||
|
||||
level._UAVRig = spawn( "script_model", uavOrigin );
|
||||
level._UAVRig setModel( "c130_zoomrig" );
|
||||
level._UAVRig.angles = (0,115,0);
|
||||
level._UAVRig hide();
|
||||
|
||||
level._UAVRig thread rotateUAVRig();
|
||||
|
||||
if ( level._teamBased )
|
||||
{
|
||||
level._radarMode["allies"] = "normal_radar";
|
||||
level._radarMode["axis"] = "normal_radar";
|
||||
level._activeUAVs["allies"] = 0;
|
||||
level._activeUAVs["axis"] = 0;
|
||||
level._activeCounterUAVs["allies"] = 0;
|
||||
level._activeCounterUAVs["axis"] = 0;
|
||||
level._uavModels["allies"] = [];
|
||||
level._uavModels["axis"] = [];
|
||||
|
||||
if( level._multiTeamBased )
|
||||
{
|
||||
for( i = 0; i < level._teamNameList.size; i++ )
|
||||
{
|
||||
level._radarMode[level._teamNameList[i]] = "normal_radar";
|
||||
level._activeUAVs[level._teamNameList[i]] = 0;
|
||||
level._activeCounterUAVs[level._teamNameList[i]] = 0;
|
||||
level._uavModels[level._teamNameList[i]] = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
level._radarMode = [];
|
||||
level._activeUAVs = [];
|
||||
level._activeCounterUAVs = [];
|
||||
|
||||
level._uavModels = [];
|
||||
|
||||
level thread onPlayerConnect();
|
||||
}
|
||||
|
||||
level thread UAVTracker();
|
||||
}
|
||||
|
||||
|
||||
onPlayerConnect()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
level waittill( "connected", player );
|
||||
|
||||
level._activeUAVs[ player.guid ] = 0;
|
||||
level._activeCounterUAVs[ player.guid ] = 0;
|
||||
|
||||
level._radarMode[ player.guid ] = "normal_radar";
|
||||
}
|
||||
}
|
||||
|
||||
rotateUAVRig()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
self rotateyaw( -360, 60 );
|
||||
wait ( 60 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
launchUAV( owner, team, duration, isCounter )
|
||||
{
|
||||
UAVModel = spawn( "script_model", level._UAVRig getTagOrigin( "tag_origin" ) );
|
||||
|
||||
UAVModel setModel( "vehicle_uav_static_mp" );
|
||||
|
||||
UAVModel thread damageTracker( isCounter );
|
||||
UAVModel.team = team;
|
||||
UAVModel.owner = owner;
|
||||
|
||||
UAVModel thread handleIncomingStinger();
|
||||
|
||||
addUAVModel( UAVModel );
|
||||
|
||||
zOffset = randomIntRange( 3000, 5000 );
|
||||
|
||||
angle = randomInt( 360 );
|
||||
radiusOffset = randomInt( 2000 ) + 5000;
|
||||
|
||||
xOffset = cos( angle ) * radiusOffset;
|
||||
yOffset = sin( angle ) * radiusOffset;
|
||||
|
||||
angleVector = vectorNormalize( (xOffset,yOffset,zOffset) );
|
||||
angleVector = vector_multiply( angleVector, randomIntRange( 6000, 7000 ) );
|
||||
|
||||
UAVModel linkTo( level._UAVRig, "tag_origin", angleVector, (0,angle - 90,0) );
|
||||
|
||||
UAVModel thread updateUAVModelVisibility();
|
||||
|
||||
if ( isCounter )
|
||||
UAVModel addActiveCounterUAV();
|
||||
else
|
||||
UAVModel addActiveUAV();
|
||||
|
||||
level notify ( "uav_update" );
|
||||
|
||||
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", duration - 7 );
|
||||
|
||||
if ( UAVModel.health <= 0 )
|
||||
{
|
||||
forward = vector_multiply( anglesToRight( UAVModel.angles ), 200 );
|
||||
playFx ( level._uav_fx[ "explode" ], UAVModel.origin, forward );
|
||||
}
|
||||
else
|
||||
{
|
||||
UAVModel unlink();
|
||||
|
||||
destPoint = UAVModel.origin + vector_multiply( anglestoforward( UAVModel.angles ), 20000 );
|
||||
UAVModel moveTo( destPoint, 60 );
|
||||
PlayFXOnTag( level._effect[ "ac130_engineeffect" ] , UAVModel, "tag_origin" );
|
||||
|
||||
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", 3 );
|
||||
|
||||
UAVModel moveTo( destPoint, 4, 4, 0.0 );
|
||||
|
||||
UAVModel waittill_notify_or_timeout_hostmigration_pause( "death", 4 );
|
||||
}
|
||||
|
||||
if ( isCounter )
|
||||
UAVModel removeActiveCounterUAV();
|
||||
else
|
||||
UAVModel removeActiveUAV();
|
||||
|
||||
UAVModel delete();
|
||||
removeUAVModel( UAVModel );
|
||||
|
||||
level notify ( "uav_update" );
|
||||
}
|
||||
|
||||
monitorUAVStrike()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
for ( ;; )
|
||||
{
|
||||
msg = self waittill_any_return( "death", "uav_strike_cancel", "uav_strike_successful" );
|
||||
if ( msg == "uav_strike_successful" )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
showLazeMessage()
|
||||
{
|
||||
msg = self maps\mp\gametypes\_hud_util::createFontString( "bigfixed", 0.75 );
|
||||
msg maps\mp\gametypes\_hud_util::setPoint( "CENTER", "CENTER", 0 , 150 );
|
||||
msg setText( &"MP_LASE_TARGET_FOR_PREDATOR_STRIKE" );
|
||||
|
||||
self waittill_any_timeout( 4.0, "death", "uav_strike_cancel", "uav_strike_successful" );
|
||||
|
||||
msg destroyElem();
|
||||
}
|
||||
|
||||
waitForLazeDiscard()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
self endon( "uav_strike_used" );
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill ( "weapon_change", newWeapon );
|
||||
|
||||
if ( newWeapon != "uavstrikebinoculars_mp" )
|
||||
{
|
||||
self notify( "uav_strike_cancel" );
|
||||
break;
|
||||
}
|
||||
else
|
||||
wait( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
waitForLazedTarget()
|
||||
{
|
||||
level endon( "game_ended" );
|
||||
self endon( "death" );
|
||||
|
||||
self thread showLazeMessage();
|
||||
self thread waitForLazeDiscard();
|
||||
|
||||
weapon = self getLastWeapon();
|
||||
secondaryWeapon = undefined;
|
||||
primaryWeapons = self GetWeaponsListPrimaries();
|
||||
foreach ( primaryWeapon in primaryWeapons )
|
||||
{
|
||||
if ( primaryWeapon != weapon )
|
||||
{
|
||||
secondaryWeapon = primaryWeapon;
|
||||
self takeWeapon( secondaryWeapon );
|
||||
break;
|
||||
}
|
||||
}
|
||||
self _giveWeapon("uavstrikebinoculars_mp");
|
||||
self switchToWeapon( "uavstrikebinoculars_mp" );
|
||||
|
||||
traceData = undefined;
|
||||
for(;;)
|
||||
{
|
||||
msg = self waittill_any_return( "weapon_fired", "uav_strike_cancel" );
|
||||
|
||||
if ( msg == "uav_strike_cancel" )
|
||||
break;
|
||||
|
||||
origin = self GetEye();
|
||||
forward = AnglesToForward( self GetPlayerAngles() );
|
||||
endpoint = origin + forward * 15000;
|
||||
|
||||
traceData = BulletTrace( origin, endpoint, true, self );
|
||||
if ( isDefined(traceData["position"]) )
|
||||
break;
|
||||
}
|
||||
|
||||
if ( isDefined( traceData ) )
|
||||
{
|
||||
|
||||
targetPosition = traceData["position"];
|
||||
|
||||
fxEnt = SpawnFx( level._effect[ "laserTarget" ], targetPosition);
|
||||
TriggerFx( fxEnt );
|
||||
fxEnt thread waitFxEntDie();
|
||||
|
||||
magicBullet( "uav_strike_projectile_mp", targetPosition + (0,0,4000) , targetPosition, self );
|
||||
self notify( "uav_strike_used" );
|
||||
}
|
||||
|
||||
self takeWeapon( "uavstrikebinoculars_mp" );
|
||||
if ( msg != "uav_strike_cancel" )
|
||||
self switchToWeapon( weapon );
|
||||
if ( isDefined( secondaryWeapon ) )
|
||||
self _giveWeapon( secondaryWeapon );
|
||||
|
||||
if ( isDefined( traceData ) )
|
||||
self notify( "uav_strike_successful" );
|
||||
}
|
||||
|
||||
waitFxEntDie()
|
||||
{
|
||||
wait( 2 );
|
||||
self delete();
|
||||
}
|
||||
|
||||
waittill_notify_or_timeout_hostmigration_pause( msg, timer )
|
||||
{
|
||||
self endon( msg );
|
||||
|
||||
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( timer );
|
||||
}
|
||||
|
||||
|
||||
updateUAVModelVisibility()
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill_either ( "joined_team", "uav_update" );
|
||||
|
||||
self hide();
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( level._teamBased )
|
||||
{
|
||||
if ( player.team != self.team )
|
||||
self showToPlayer( player );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( isDefined( self.owner ) && player == self.owner )
|
||||
continue;
|
||||
|
||||
self showToPlayer( player );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
damageTracker( isCounterUAV )
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
self setCanDamage( true );
|
||||
self.maxhealth = 700;
|
||||
self.health = self.maxhealth;
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
self waittill ( "damage", damage, attacker, direction_vec, point, sMeansOfDeath );
|
||||
|
||||
if ( !isPlayer( attacker ) )
|
||||
{
|
||||
if ( !isDefined( self ) )
|
||||
return;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "" );
|
||||
|
||||
if ( attacker _hasPerk( "specialty_armorpiercing" ) && isDefined( self ) )
|
||||
{
|
||||
damageAdd = damage*level._armorPiercingMod;
|
||||
self.health -= int(damageAdd);
|
||||
}
|
||||
|
||||
if ( !isDefined( self ) )
|
||||
{
|
||||
if ( isPlayer( attacker ) && (!isDefined(self.owner) || attacker != self.owner) )
|
||||
{
|
||||
if ( isCounterUAV )
|
||||
thread teamPlayerCardSplash( "callout_destroyed_counter_uav", attacker );
|
||||
else
|
||||
thread teamPlayerCardSplash( "callout_destroyed_uav", attacker );
|
||||
|
||||
thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, damage, sMeansOfDeath );
|
||||
attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 50 );
|
||||
attacker notify( "destroyed_killstreak" );
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tryUseUAV( lifeId )
|
||||
{
|
||||
return useUAV( "uav" );
|
||||
}
|
||||
|
||||
|
||||
tryUseDoubleUAV( lifeId )
|
||||
{
|
||||
return useUAV( "double_uav" );
|
||||
}
|
||||
|
||||
|
||||
tryUseCounterUAV( lifeId )
|
||||
{
|
||||
return useUAV( "counter_uav" );
|
||||
}
|
||||
|
||||
|
||||
UAVStrikeSetup()
|
||||
{
|
||||
self.usedStrikeUAV = 0;
|
||||
}
|
||||
|
||||
tryUseUAVStrike( lifeId )
|
||||
{
|
||||
if ( self.usedStrikeUAV == 0 )
|
||||
{
|
||||
self.usedStrikeUAV = 1;
|
||||
//useUAV( "uav_strike" );
|
||||
}
|
||||
self thread waitForLazedTarget();
|
||||
return monitorUAVStrike();
|
||||
}
|
||||
|
||||
useUAV( uavType )
|
||||
{
|
||||
self maps\mp\_matchdata::logKillstreakEvent( uavType, self.origin );
|
||||
|
||||
team = self.pers["team"];
|
||||
useTime = level._radarViewTime;
|
||||
|
||||
level thread launchUAV( self, team, useTime, uavType == "counter_uav" );
|
||||
|
||||
if ( uavType == "counter_uav" )
|
||||
self notify( "used_counter_uav" );
|
||||
else
|
||||
self notify( "used_uav" );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
UAVTracker()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill ( "uav_update" );
|
||||
|
||||
if ( level._multiTeamBased )
|
||||
{
|
||||
for( i = 0; i < level._teamNameList.size; i++ )
|
||||
{
|
||||
updateTeamUAVStatus( level._teamNameList[i] );
|
||||
}
|
||||
}
|
||||
else if ( level._teamBased )
|
||||
{
|
||||
updateTeamUAVStatus( "allies" );
|
||||
updateTeamUAVStatus( "axis" );
|
||||
}
|
||||
else
|
||||
{
|
||||
updatePlayersUAVStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
updateTeamUAVStatus( team )
|
||||
{
|
||||
activeUAVs = level._activeUAVs[team];
|
||||
activeCounterUAVs = 0;
|
||||
|
||||
if( level._multiTeamBased )
|
||||
{
|
||||
for( i = 0; i < level._teamNameList.size; i++ )
|
||||
{
|
||||
if( team != level._teamNameList[i] )
|
||||
{
|
||||
activeCounterUAVs += level._activeCounterUAVs[level._teamNameList[i]];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
activeCounterUAVs = level._activeCounterUAVs[level._otherTeam[team]];
|
||||
}
|
||||
|
||||
if ( !activeCounterUAVs )
|
||||
unblockTeamRadar( team );
|
||||
else
|
||||
blockTeamRadar( team );
|
||||
|
||||
if ( !activeUAVs )
|
||||
{
|
||||
setTeamRadarWrapper( team, 0 );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( activeUAVs > 1 )
|
||||
level._radarMode[team] = "fast_radar";
|
||||
else
|
||||
level._radarMode[team] = "normal_radar";
|
||||
|
||||
updateTeamUAVType();
|
||||
setTeamRadarWrapper( team, 1 );
|
||||
}
|
||||
|
||||
|
||||
updatePlayersUAVStatus()
|
||||
{
|
||||
totalActiveCounterUAVs = 0;
|
||||
counterUAVPlayer = undefined;
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
activeUAVs = level._activeUAVs[ player.guid ];
|
||||
activeCounterUAVs = level._activeCounterUAVs[ player.guid ];
|
||||
|
||||
if ( activeCounterUAVs )
|
||||
{
|
||||
totalActiveCounterUAVs++;
|
||||
counterUAVPlayer = player;
|
||||
}
|
||||
|
||||
if ( !activeUAVs )
|
||||
{
|
||||
player.hasRadar = false;
|
||||
if( player.radarMode != "directional_radar" )
|
||||
{
|
||||
player.radarMode = "normal_radar";
|
||||
player.nextRadarMode = "normal_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
player.nextRadarMode = "normal_radar";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( activeUAVs > 1 )
|
||||
if( player.radarMode != "directional_radar" )
|
||||
{
|
||||
player.radarMode = "fast_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
player.nextRadarMode = "fast_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
if( player.radarMode != "directional_radar" )
|
||||
{
|
||||
player.radarMode = "normal_radar";
|
||||
player.nextRadarMode = "normal_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
player.nextRadarMode = "normal_radar";
|
||||
}
|
||||
}
|
||||
|
||||
player.hasRadar = true;
|
||||
}
|
||||
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( !totalActiveCounterUAVs )
|
||||
{
|
||||
player.isRadarBlocked = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( totalActiveCounterUAVs == 1 && player == counterUAVPlayer )
|
||||
player.isRadarBlocked = false;
|
||||
else
|
||||
player.isRadarBlocked = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
blockPlayerUAV()
|
||||
{
|
||||
self endon ( "disconnect" );
|
||||
|
||||
self notify ( "blockPlayerUAV" );
|
||||
self endon ( "blockPlayerUAV" );
|
||||
|
||||
self.isRadarBlocked = true;
|
||||
|
||||
wait ( level._uavBlockTime );
|
||||
|
||||
self.isRadarBlocked = false;
|
||||
|
||||
//self iPrintLn( &"MP_WAR_COUNTER_RADAR_EXPIRED" );
|
||||
}
|
||||
|
||||
|
||||
updateTeamUAVType()
|
||||
{
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == "spectator" )
|
||||
continue;
|
||||
|
||||
if( player.radarMode != "directional_radar" )
|
||||
{
|
||||
player.radarMode = level._radarMode[player.team];
|
||||
}
|
||||
else
|
||||
{
|
||||
player.nextRadarMode = level._radarMode[player.team];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
usePlayerUAV( doubleUAV, useTime )
|
||||
{
|
||||
level endon("game_ended");
|
||||
self endon("disconnect");
|
||||
|
||||
self notify ( "usePlayerUAV" );
|
||||
self endon ( "usePlayerUAV" );
|
||||
|
||||
if ( doubleUAV )
|
||||
{
|
||||
if( self.radarMode != "directional_radar" )
|
||||
{
|
||||
self.radarMode = "fast_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
self.nextRadarMode = "fast_radar";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if( self.radarMode != "directional_radar" )
|
||||
{
|
||||
self.radarMode = "normal_radar";
|
||||
self.nextRadarMode = "normal_radar";
|
||||
}
|
||||
else
|
||||
{
|
||||
self.nextRadarMode = "normal_radar";
|
||||
}
|
||||
}
|
||||
|
||||
self.hasRadar = true;
|
||||
|
||||
wait ( useTime );
|
||||
|
||||
if( self.radarMode != "directional_radar" )
|
||||
{
|
||||
self.hasRadar = false;
|
||||
}
|
||||
|
||||
//self iPrintLn( &"MP_WAR_RADAR_EXPIRED" );
|
||||
}
|
||||
|
||||
|
||||
setTeamRadarWrapper( team, value )
|
||||
{
|
||||
setTeamRadar( team, value );
|
||||
level notify( "radar_status_change", team );
|
||||
}
|
||||
|
||||
|
||||
|
||||
handleIncomingStinger()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
self endon ( "death" );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
level waittill ( "stinger_fired", player, missile, lockTarget );
|
||||
|
||||
if ( !IsDefined( lockTarget ) || (lockTarget != self) )
|
||||
continue;
|
||||
|
||||
missile thread stingerProximityDetonate( lockTarget, player );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stingerProximityDetonate( targetEnt, player )
|
||||
{
|
||||
self endon ( "death" );
|
||||
|
||||
minDist = distance( self.origin, targetEnt GetPointInBounds( 0, 0, 0 ) );
|
||||
lastCenter = targetEnt GetPointInBounds( 0, 0, 0 );
|
||||
|
||||
for ( ;; )
|
||||
{
|
||||
// UAV already destroyed
|
||||
if ( !isDefined( targetEnt ) )
|
||||
center = lastCenter;
|
||||
else
|
||||
center = targetEnt GetPointInBounds( 0, 0, 0 );
|
||||
|
||||
lastCenter = center;
|
||||
|
||||
curDist = distance( self.origin, center );
|
||||
|
||||
if ( curDist < minDist )
|
||||
minDist = curDist;
|
||||
|
||||
if ( curDist > minDist )
|
||||
{
|
||||
if ( curDist > 1536 )
|
||||
return;
|
||||
|
||||
radiusDamage( self.origin, 1536, 600, 600, player );
|
||||
playFx( level._stingerFXid, self.origin );
|
||||
|
||||
//self playSound( "remotemissile_explode" );
|
||||
self hide();
|
||||
|
||||
self notify("deleted");
|
||||
wait ( 0.05 );
|
||||
self delete();
|
||||
player notify( "killstreak_destroyed" );
|
||||
}
|
||||
|
||||
wait ( 0.05 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addUAVModel( UAVModel )
|
||||
{
|
||||
if ( level._teamBased )
|
||||
level._UAVModels[UAVModel.team][level._UAVModels[UAVModel.team].size] = UAVModel;
|
||||
else
|
||||
level._UAVModels[UAVModel.owner.guid + "_" + getTime()] = UAVModel;
|
||||
}
|
||||
|
||||
|
||||
removeUAVModel( UAVModel )
|
||||
{
|
||||
UAVModels = [];
|
||||
|
||||
if ( level._teamBased )
|
||||
{
|
||||
team = UAVModel.team;
|
||||
|
||||
foreach ( uavModel in level._UAVModels[team] )
|
||||
{
|
||||
if ( !isDefined( uavModel ) )
|
||||
continue;
|
||||
|
||||
UAVModels[UAVModels.size] = uavModel;
|
||||
}
|
||||
|
||||
level._UAVModels[team] = UAVModels;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( uavModel in level._UAVModels )
|
||||
{
|
||||
if ( !isDefined( uavModel ) )
|
||||
continue;
|
||||
|
||||
UAVModels[UAVModels.size] = uavModel;
|
||||
}
|
||||
|
||||
level._UAVModels = UAVModels;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
addActiveUAV()
|
||||
{
|
||||
if ( level._teamBased )
|
||||
level._activeUAVs[self.team]++;
|
||||
else
|
||||
level._activeUAVs[self.owner.guid]++;
|
||||
/*
|
||||
if ( level._teamBased )
|
||||
{
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == self.team )
|
||||
player iPrintLn( &"MP_WAR_RADAR_ACQUIRED", self.owner, level._radarViewTime );
|
||||
else if ( player.team == level._otherTeam[self.team] )
|
||||
player iPrintLn( &"MP_WAR_RADAR_ACQUIRED_ENEMY", level._radarViewTime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player == self.owner )
|
||||
player iPrintLn( &"MP_WAR_RADAR_ACQUIRED", self.owner, level._radarViewTime );
|
||||
else
|
||||
player iPrintLn( &"MP_WAR_RADAR_ACQUIRED_ENEMY", level._radarViewTime );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
addActiveCounterUAV()
|
||||
{
|
||||
if ( level._teamBased )
|
||||
level._activeCounterUAVs[self.team]++;
|
||||
else
|
||||
level._activeCounterUAVs[self.owner.guid]++;
|
||||
/*
|
||||
if ( level._teamBased )
|
||||
{
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player.team == self.team )
|
||||
player iPrintLn( &"MP_WAR_COUNTER_RADAR_ACQUIRED", self.owner, level._uavBlockTime );
|
||||
else if ( player.team == level._otherTeam[self.team] )
|
||||
player iPrintLn( &"MP_WAR_COUNTER_RADAR_ACQUIRED_ENEMY", level._uavBlockTime );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach ( player in level._players )
|
||||
{
|
||||
if ( player == self.owner )
|
||||
player iPrintLn( &"MP_WAR_COUNTER_RADAR_ACQUIRED", self.owner, level._uavBlockTime );
|
||||
else
|
||||
player iPrintLn( &"MP_WAR_COUNTER_RADAR_ACQUIRED_ENEMY", level._uavBlockTime );
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
removeActiveUAV()
|
||||
{
|
||||
if ( level._teamBased )
|
||||
{
|
||||
level._activeUAVs[self.team]--;
|
||||
|
||||
if ( !level._activeUAVs[self.team] )
|
||||
{
|
||||
//printOnTeam( &"MP_WAR_RADAR_EXPIRED", self.team );
|
||||
//printOnTeam( &"MP_WAR_RADAR_EXPIRED_ENEMY", level._otherTeam[self.team] );
|
||||
}
|
||||
}
|
||||
else if ( isDefined( self.owner ) )
|
||||
{
|
||||
level._activeUAVs[self.owner.guid]--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
removeActiveCounterUAV()
|
||||
{
|
||||
if ( level._teamBased )
|
||||
{
|
||||
level._activeCounterUAVs[self.team]--;
|
||||
|
||||
if ( !level._activeCounterUAVs[self.team] )
|
||||
{
|
||||
//printOnTeam( &"MP_WAR_COUNTER_RADAR_EXPIRED", self.team );
|
||||
//printOnTeam( &"MP_WAR_COUNTER_RADAR_EXPIRED_ENEMY", level._otherTeam[self.team] );
|
||||
}
|
||||
}
|
||||
else if ( isDefined( self.owner ) )
|
||||
{
|
||||
level._activeCounterUAVs[self.owner.guid]--;
|
||||
}
|
||||
}
|
||||
|
||||
MeleeUAV()
|
||||
{
|
||||
level endon ( "game_ended" );
|
||||
self endon ( "disconnect" );
|
||||
|
||||
self.radarMode = "directional_radar";
|
||||
// self.hasRadar = true;
|
||||
|
||||
wait ( 5 );
|
||||
|
||||
// self.hasRadar = false;
|
||||
if( isDefined( self.nextRadarMode ))
|
||||
{
|
||||
self.radarMode = self.nextRadarMode;
|
||||
}
|
||||
else
|
||||
{
|
||||
self.radarMode = "normal_radar";
|
||||
}
|
||||
}
|
204
maps/mp/killstreaks/_weapdrop.gsc
Normal file
204
maps/mp/killstreaks/_weapdrop.gsc
Normal file
@ -0,0 +1,204 @@
|
||||
#include maps\mp\_utility;
|
||||
#include common_scripts\utility;
|
||||
|
||||
|
||||
// Each Killstreak has its own initialization function. This Script has two main purposes.
|
||||
// (1). All global data and assets used by this killstreak should be initialized here.
|
||||
// (2). The callback that executes when a player activates this killstreak should be set here.
|
||||
// TODO: A call to this script must be added to the script init() in the file c:\trees\nx1\game\share\raw\maps\mp\killstreaks\_killstreaks.gsc,
|
||||
// this is were each individual killstreak is initialized.
|
||||
init()
|
||||
{
|
||||
//This is a good place to precache assets, load up fx, or setup any global data that might be needed, NOTE: Everything defined in killstreakTable.csv
|
||||
//will be precached automatically ( see initKillstreakData() in _killstreaks.gsc if interested ) so you do not need to worry about initializing the
|
||||
//strings/weapons/materials/sounds defined there. If, for example, you were going to manually script up a plane flyiing over when this killstreak was
|
||||
//activated you would want to precache that model here.
|
||||
|
||||
|
||||
//generally any global data that is needed would be stored in the level object, here is an example
|
||||
//level._effect[ "emp_flash" ] = loadfx( "explosions/emp_flash_mp" );
|
||||
|
||||
|
||||
//This is were the killstreak activation callback is set
|
||||
//TODO: Replace "killstreak_template" with the name of the new killstreak as defined in killstreakTable.csv
|
||||
//Most killstreaks use a try fuction ( which i recommend, even if it is not necessary for this particualr killstreak it is nice to have a consistent model )
|
||||
//the try script will make sure it is ok to fire the killstreak before the actual killstreak script is called.
|
||||
|
||||
precacheString ( &"MP_AIR_SPACE_TOO_CROWDED" );
|
||||
precacheString ( &"MP_HOLD_USERELOAD_TO_THROWAWAY" );
|
||||
|
||||
level._killstreakFuncs["weapdrop"] = ::try_use_weapdrop;
|
||||
|
||||
//Use this script to update/initialize players as they connect to the game
|
||||
level thread onPlayerConnect();
|
||||
}
|
||||
|
||||
|
||||
// This script is running on the global level object, it monitors players connecting to the game.
|
||||
// Its main purpose is to apply the onPlayerSpawned script to each player as they connect to the game.
|
||||
onPlayerConnect()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
level waittill("connected", player);
|
||||
player thread onPlayerSpawned();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// This script is running on each player in the game, it recieves a notification each time the player it is running on spawns in the game
|
||||
// Its main purpose is to initialize any per player data, as well as update the player subject to any global killstreak data when that player spawns.
|
||||
onPlayerSpawned()
|
||||
{
|
||||
self endon("disconnect");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
self waittill( "spawned_player" );
|
||||
println( "player spwaned" );
|
||||
|
||||
// init/manage any per player killstreak data here
|
||||
}
|
||||
}
|
||||
|
||||
//Many of the killstreaks have a try block that will test level conditions to make sure it is ok to fire the killstreak now. A good example of this is for the air killstreaks.
|
||||
//Only a certain number of vehicles are allowed in the air at any given time, so if the airspace is full and the killstreak cannot be fired this try should return false.
|
||||
//If there are any preconditions that must be met in order to fire this killstreak they should be checked in this script.
|
||||
//NOTE: If this script returns true the killstreak system will consider this killstreak usage complete and the dpad icon will be removed, if this script returns false nothing will
|
||||
//change and the system will just continue to wait for the the player to activate the killstreak by pressing right on the dpad.
|
||||
try_use_weapdrop()
|
||||
{
|
||||
is_ok_to_use_killstreak = true;
|
||||
|
||||
if( is_ok_to_use_killstreak )
|
||||
{
|
||||
weapdrop_use();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// This is the callback that executes when the killstreak is activated by a player pressing on the dpad. This is called from the script killstreakUsePressed()
|
||||
// located in the file _killstreaks.gsc
|
||||
weapdrop_use()
|
||||
{
|
||||
assert( isDefined( self ) );
|
||||
//println( "Killstreak Template Fired!!" );
|
||||
|
||||
/*
|
||||
// don't allow use if theres 3 or more little birds up in the air already. this is consistent with the care package drop ks.
|
||||
if ( level._littleBirds >= 3 )
|
||||
{
|
||||
self iPrintLnBold( &"MP_AIR_SPACE_TOO_CROWDED" );
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
weapdrop_weapon = undefined;
|
||||
|
||||
// randomInt is confusing. 0 based and the number passed is how many ints it can return. 4 = 0-3.
|
||||
switch( randomInt( 4 ) )
|
||||
{
|
||||
case 0:
|
||||
weapdrop_weapon = "augks_mp";
|
||||
break;
|
||||
case 1:
|
||||
weapdrop_weapon = "xm25ks_mp";
|
||||
break;
|
||||
case 2:
|
||||
weapdrop_weapon = "aa12_akimbo_mp";
|
||||
break;
|
||||
case 3:
|
||||
weapdrop_weapon = "javelinks_mp";
|
||||
break;
|
||||
}
|
||||
|
||||
// spawn a new script to give and switch to the weapdrop weapon
|
||||
// the drop ks's need to return true asap otherwise you're still holding the trigger in your hand
|
||||
self thread weapdrop_equip( weapdrop_weapon );
|
||||
return true;
|
||||
}
|
||||
|
||||
weapdrop_equip( weapdrop_weapon )
|
||||
{
|
||||
self endon( "death" );
|
||||
self endon( "disconnect" );
|
||||
|
||||
assert( isDefined( weapdrop_weapon ) );
|
||||
|
||||
// hack. sometimes getCurrentWeapon will return none but getWeaponsListPrimaries wont...hmm...
|
||||
/*
|
||||
initial_weapon = self getCurrentWeapon();
|
||||
if ( initial_weapon == "none" )
|
||||
{
|
||||
weapList = self GetWeaponsListPrimaries();
|
||||
initial_weapon = weapList[0];
|
||||
}
|
||||
//printLn( initial_weapon );
|
||||
*/
|
||||
|
||||
|
||||
// make sure the script that spawned this one has returned true before I switch your weapon. this is probably unnecessary.
|
||||
wait .1;
|
||||
|
||||
// akimbo weapons must be given a specific way.
|
||||
if ( weapdrop_weapon == "aa12_akimbo_mp" )
|
||||
{
|
||||
self giveWeapon( weapdrop_weapon, 0 , true );
|
||||
}
|
||||
else
|
||||
{
|
||||
self giveWeapon( weapdrop_weapon );
|
||||
}
|
||||
|
||||
self switchToWeapon( weapdrop_weapon );
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
// when you run out of ammo, switch back to your first primary and take the weapdrop weapon
|
||||
if ( self hasWeapon ( weapdrop_weapon ) )
|
||||
{
|
||||
if ( self getAmmoCount( weapdrop_weapon ) == 0 )
|
||||
{
|
||||
//self switchToWeapon( initial_weapon );
|
||||
self takeWeapon ( weapdrop_weapon );
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
wait 0.05;
|
||||
}
|
||||
//printLn( "NO LONGER HAS KS WEAPON" );
|
||||
}
|
||||
|
||||
weapdrop_hud()
|
||||
{
|
||||
hudelem = newClientHudElem( self );
|
||||
// put something on screen that tells you, you can throw away this weapon
|
||||
hudelem.x = -30;
|
||||
hudelem.y = -20;
|
||||
hudelem.alignX = "left";
|
||||
hudelem.alignY = "bottom";
|
||||
hudelem.horzAlign = "center";
|
||||
hudelem.vertAlign = "bottom";
|
||||
hudelem.sort = 1;// force to draw after the background
|
||||
hudelem.foreground = true;
|
||||
hudelem SetText( &"MP_HOLD_USERELOAD_TO_THROWAWAY" );
|
||||
hudelem.alpha = 0;
|
||||
hudelem FadeOverTime( 0.2 );
|
||||
hudelem.alpha = 1;
|
||||
hudelem.hidewheninmenu = true;
|
||||
hudelem.fontScale = 1.25;
|
||||
hudelem.font = "fwmed";
|
||||
//hudelem.color = ( getdvarfloat( "color_neutral_r" ), getdvarfloat( "color_neutral_g" ), getdvarfloat( "color_neutral_b" ) );
|
||||
//hudelem SetPulseFX( 30, duration, 700 );// something, decay start, decay duration
|
||||
|
||||
self waittill_any( "death", "disconnect", "weapdrop_done" );
|
||||
|
||||
hudelem Destroy();
|
||||
}
|
Reference in New Issue
Block a user