Pushed raw files

This commit is contained in:
RezTech committed 2017-07-08 14:47:21 -04:00
1 parent 22d0d4d39f
commit 79f967ecc9
5854 files changed
+2989978

No files matched your search

File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+705
View File
@@ -0,0 +1,705 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
SENTRY_MODE_ON = "sentry";
SENTRY_MODE_OFF = "sentry_offline";
SENTRY_TIME_OUT = 90.0;
SENTRY_SPINUP_TIME = .05;
SENTRY_OVERHEAT_TIME = 8.0;
SENTRY_FX_TIME = .3;
init()
{
level.sentryType = [];
level.sentryType[ "sentry_minigun" ] = "sentry";
level.killStreakFuncs[ level.sentryType[ "sentry_minigun" ] ] = ::tryUseAutoSentry;
level.sentrySettings = [];
level.sentrySettings[ "sentry_minigun" ] = spawnStruct();
level.sentrySettings[ "sentry_minigun" ].burstMin = 20;
level.sentrySettings[ "sentry_minigun" ].burstMax = 120;
level.sentrySettings[ "sentry_minigun" ].pauseMin = 0.15;
level.sentrySettings[ "sentry_minigun" ].pauseMax = 0.35;
level.sentrySettings[ "sentry_minigun" ].weaponInfo = "sentry_minigun_mp";
level.sentrySettings[ "sentry_minigun" ].modelBase = "sentry_minigun";
level.sentrySettings[ "sentry_minigun" ].modelPlacement = "sentry_minigun_obj";
level.sentrySettings[ "sentry_minigun" ].modelPlacementFailed = "sentry_minigun_obj_red";
level.sentrySettings[ "sentry_minigun" ].modelDestroyed = "sentry_minigun_destroyed";
foreach ( sentryInfo in level.sentrySettings )
{
precacheItem( sentryInfo.weaponInfo );
precacheModel( sentryInfo.modelBase );
precacheModel( sentryInfo.modelPlacement );
precacheModel( sentryInfo.modelPlacementFailed );
precacheModel( sentryInfo.modelDestroyed );
}
level._effect[ "sentry_overheat_mp" ] = loadfx( "smoke/sentry_turret_overheat_smoke" );
level._effect[ "sentry_explode_mp" ] = loadfx( "explosions/sentry_gun_explosion" );
level._effect[ "sentry_smoke_mp" ] = loadfx( "smoke/car_damage_blacksmoke" );
}
/* ============================
Killstreak Functions
============================ */
tryUseAutoSentry( lifeId )
{
result = self giveSentry( "sentry_minigun" );
if ( result )
self maps\mp\_matchdata::logKillstreakEvent( "sentry", self.origin );
return ( result );
}
tryUseAutoGlSentry( lifeId )
{
result = self giveSentry( "sentry_gun" );
if ( result )
self maps\mp\_matchdata::logKillstreakEvent( "sentry_gl", self.origin );
return ( result );
}
giveSentry( sentryType )
{
self.last_sentry = sentryType;
sentryGun = createSentryForPlayer( sentryType, self );
self setCarryingSentry( sentryGun, true );
// if we failed to place the sentry, it will have been deleted at this point
if ( isDefined( sentryGun ) )
return true;
else
return false;
}
/* ============================
Player Functions
============================ */
setCarryingSentry( sentryGun, allowCancel )
{
self endon ( "death" );
self endon ( "disconnect" );
assert( isReallyAlive( self ) );
sentryGun sentry_setCarried( self );
self _disableWeapon();
self notifyOnPlayerCommand( "place_sentry", "+attack" );
self notifyOnPlayerCommand( "cancel_sentry", "+actionslot 4" );
for ( ;; )
{
result = waittill_any_return( "place_sentry", "cancel_sentry" );
if ( result == "cancel_sentry" )
{
if ( !allowCancel )
continue;
sentryGun sentry_setCancelled();
self _enableWeapon();
return false;
}
if ( !sentryGun.canBePlaced )
continue;
sentryGun sentry_setPlaced();
self _enableWeapon();
return true;
}
}
/* ============================
Sentry Functions
============================ */
createSentryForPlayer( sentryType, owner )
{
assertEx( isDefined( owner ), "createSentryForPlayer() called without owner specified" );
sentryGun = spawnTurret( "misc_turret", owner.origin, level.sentrySettings[ sentryType ].weaponInfo );
sentryGun.angles = owner.angles;
sentryGun sentry_initSentry( sentryType, owner );
return ( sentryGun );
}
sentry_initSentry( sentryType, owner )
{
self.sentryType = sentryType;
self setModel( level.sentrySettings[ self.sentryType ].modelBase );
self.health = 1000;
self setCanDamage( true );
self makeTurretInoperable();
self setTurretModeChangeWait( true );
// self setConvergenceTime( .25, "pitch" );
// self setConvergenceTime( .25, "yaw" );
self sentry_setInactive();
self setDefaultDropPitch( -89.0 ); // setting this mainly prevents Turret_RestoreDefaultDropPitch() from running
self sentry_setOwner( owner );
self thread sentry_handleOwner();
self thread sentry_handleDamage();
self thread sentry_handleDeath();
self thread sentry_handleUse();
self thread sentry_timeOut();
self thread sentry_attackTargets();
self thread sentry_beepSounds();
}
/* ============================
Sentry Handlers
============================ */
sentry_handleDamage()
{
// use a health buffer to prevent the turret from dying to friendly fire
healthBuffer = 20000;
self.health += healthbuffer;
while ( self.health > 0 )
{
self waittill( "damage", amount, attacker, dir, point, type );
if ( isDefined( attacker ) && isPlayer( attacker ) && attacker != self.owner && attacker isFriendlyToSentry( self ) && !isDefined( level.nukeDetonated ) )
{
self.health += amount;
continue;
}
// 7x damage for explosives - GRENADES
if ( isExplosiveDamage( type ) )
self.health -= (amount * 1);
if ( type == "MOD_MELEE" )
self.health = 0;
if ( isPlayer( attacker ) )
{
attacker maps\mp\gametypes\_damagefeedback::updateDamageFeedback( "sentry" );
if ( attacker _hasPerk( "specialty_armorpiercing" ) )
{
damageAdd = amount*level.armorPiercingMod;
self.health -= int(damageAdd);
}
}
if ( self.health - healthbuffer < 0 )
{
thread maps\mp\gametypes\_missions::vehicleKilled( self.owner, self, undefined, attacker, amount, type );
if ( isPlayer( attacker ) && (!isDefined(self.owner) || attacker != self.owner) )
{
attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", 100 );
attacker notify( "destroyed_killstreak" );
}
if ( isDefined( self.owner ) )
self.owner thread leaderDialogOnPlayer( "sentry_destroyed" );
self notify ( "death" );
return;
}
}
}
sentry_handleDeath()
{
entNum = self GetEntityNumber();
self addToTurretList( entNum );
self waittill ( "death" );
self removeFromTurretList( entNum );
// this handles cases of deletion
if ( !isDefined( self ) )
return;
self setModel( level.sentrySettings[ self.sentryType ].modelDestroyed );
self sentry_setInactive();
self setDefaultDropPitch( 40 );
self SetSentryOwner( undefined );
self SetTurretMinimapVisible( false );
self playSound( "sentry_explode" );
playFxOnTag( getFx( "sentry_explode_mp" ), self, "tag_aim" );
// don't try to delete ourselves if we're deleted by other means
self endon ( "death" );
wait ( 1.5 );
self playSound( "sentry_explode_smoke" );
for ( smokeTime = 8; smokeTime > 0; smokeTime -= 0.4 )
{
playFxOnTag( getFx( "sentry_smoke_mp" ), self, "tag_aim" );
wait ( 0.4 );
}
self delete();
}
sentry_handleUse()
{
self endon ( "death" );
level endon ( "game_ended" );
for ( ;; )
{
self waittill ( "trigger", player );
assert( player == self.owner );
assert( !isDefined( self.carriedBy ) );
if ( !isReallyAlive( player ) )
continue;
player setCarryingSentry( self, false );
}
}
sentry_handleOwner()
{
self endon ( "death" );
level endon ( "game_ended" );
self notify ( "sentry_handleOwner" );
self endon ( "sentry_handleOwner" );
self.owner waittill_any( "disconnect", "joined_team", "joined_spectators" );
self notify( "death" );
}
/* ============================
Sentry Utility Functions
============================ */
sentry_setOwner( owner )
{
assertEx( isDefined( owner ), "sentry_setOwner() called without owner specified" );
assertEx( isPlayer( owner ), "sentry_setOwner() called on non-player entity type: " + owner.classname );
self.owner = owner;
self SetSentryOwner( self.owner );
self SetTurretMinimapVisible( true );
if ( level.teamBased )
{
self.team = self.owner.team;
self setTurretTeam( self.team );
}
self thread sentry_handleOwner();
}
sentry_setPlaced()
{
self setModel( level.sentrySettings[ self.sentryType ].modelBase );
self setSentryCarried( false );
self setCanDamage( true );
self sentry_makeSolid();
self.carriedBy forceUseHintOff();
self.carriedBy = undefined;
self sentry_setActive();
self playSound( "sentry_gun_plant" );
self notify ( "placed" );
}
sentry_setCancelled()
{
self.carriedBy forceUseHintOff();
self delete();
}
sentry_setCarried( carrier )
{
assert( isPlayer( carrier ) );
assertEx( carrier == self.owner, "sentry_setCarried() specified carrier does not own this sentry" );
self setModel( level.sentrySettings[ self.sentryType ].modelPlacement );
self setSentryCarried( true );
self setCanDamage( false );
self sentry_makeNotSolid();
self.carriedBy = carrier;
carrier thread updateSentryPlacement( self );
self thread sentry_onCarrierDeath( carrier );
self thread sentry_onCarrierDisconnect( carrier );
self thread sentry_onGameEnded();
self sentry_setInactive();
self notify ( "carried" );
}
updateSentryPlacement( sentryGun )
{
self endon ( "death" );
self endon ( "disconnect" );
level endon ( "game_ended" );
sentryGun endon ( "placed" );
sentryGun endon ( "death" );
sentryGun.canBePlaced = true;
lastCanPlaceSentry = -1; // force initial update
for( ;; )
{
placement = self canPlayerPlaceSentry();
sentryGun.origin = placement[ "origin" ];
sentryGun.angles = placement[ "angles" ];
sentryGun.canBePlaced = self isOnGround() && placement[ "result" ];
if ( sentryGun.canBePlaced != lastCanPlaceSentry )
{
if ( sentryGun.canBePlaced )
{
sentryGun setModel( level.sentrySettings[ sentryGun.sentryType ].modelPlacement );
self ForceUseHintOn( &"SENTRY_PLACE" );
}
else
{
sentryGun setModel( level.sentrySettings[ sentryGun.sentryType ].modelPlacementFailed );
self ForceUseHintOn( &"SENTRY_CANNOT_PLACE" );
}
}
lastCanPlaceSentry = sentryGun.canBePlaced;
wait ( 0.05 );
}
}
sentry_onCarrierDeath( carrier )
{
self endon ( "placed" );
self endon ( "death" );
carrier waittill ( "death" );
if ( self.canBePlaced )
self sentry_setPlaced();
else
self delete();
}
sentry_onCarrierDisconnect( carrier )
{
self endon ( "placed" );
self endon ( "death" );
carrier waittill ( "disconnect" );
self delete();
}
sentry_onGameEnded( carrier )
{
self endon ( "placed" );
self endon ( "death" );
level waittill ( "game_ended" );
self delete();
}
sentry_setActive()
{
self setMode( SENTRY_MODE_ON );
self setCursorHint( "HINT_NOICON" );
self setHintString( &"SENTRY_PICKUP" );
self makeUsable();
foreach ( player in level.players )
{
if ( player == self.owner )
self enablePlayerUse( player );
else
self disablePlayerUse( player );
}
if ( level.teamBased )
self maps\mp\_entityheadicons::setTeamHeadIcon( self.team, (0,0,65) );
else
self maps\mp\_entityheadicons::setPlayerHeadIcon( self.owner, (0,0,65) );
}
sentry_setInactive()
{
self setMode( SENTRY_MODE_OFF );
self makeUnusable();
if ( level.teamBased )
self maps\mp\_entityheadicons::setTeamHeadIcon( "none", ( 0, 0, 0 ) );
else if ( isDefined( self.owner ) )
self maps\mp\_entityheadicons::setPlayerHeadIcon( undefined, ( 0, 0, 0 ) );
}
sentry_makeSolid()
{
self makeTurretSolid();
}
sentry_makeNotSolid()
{
self setContents( 0 );
}
isFriendlyToSentry( sentryGun )
{
if ( level.teamBased && self.team == sentryGun.team )
return true;
return false;
}
addToTurretList( entNum )
{
level.turrets[entNum] = self;
}
removeFromTurretList( entNum )
{
level.turrets[entNum] = undefined;
}
/* ============================
Sentry Logic Functions
============================ */
sentry_attackTargets()
{
self endon( "death" );
level endon( "game_ended" );
self.momentum = 0;
self.heatLevel = 0;
self.overheated = false;
self thread sentry_heatMonitor();
for ( ;; )
{
self waittill_either( "turretstatechange", "cooled" );
if ( self isFiringTurret() )
{
self thread sentry_burstFireStart();
}
else
{
self sentry_spinDown();
self thread sentry_burstFireStop();
}
}
}
sentry_timeOut()
{
self endon( "death" );
level endon ( "game_ended" );
lifeSpan = SENTRY_TIME_OUT;
while ( lifeSpan )
{
wait ( 1.0 );
maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone();
if ( !isDefined( self.carriedBy ) )
lifeSpan = max( 0, lifeSpan - 1.0 );
}
if ( isDefined( self.owner ) )
self.owner thread leaderDialogOnPlayer( "sentry_gone" );
self notify ( "death" );
}
sentry_targetLockSound()
{
self endon ( "death" );
self playSound( "sentry_gun_beep" );
wait ( 0.1 );
self playSound( "sentry_gun_beep" );
wait ( 0.1 );
self playSound( "sentry_gun_beep" );
}
sentry_spinUp()
{
self thread sentry_targetLockSound();
while ( self.momentum < SENTRY_SPINUP_TIME )
{
self.momentum += 0.1;
wait ( 0.1 );
}
}
sentry_spinDown()
{
self.momentum = 0;
}
sentry_burstFireStart()
{
self endon( "death" );
self endon( "stop_shooting" );
level endon( "game_ended" );
self sentry_spinUp();
fireTime = weaponFireTime( level.sentrySettings[ self.sentryType ].weaponInfo );
minShots = level.sentrySettings[ self.sentryType ].burstMin;
maxShots = level.sentrySettings[ self.sentryType ].burstMax;
minPause = level.sentrySettings[ self.sentryType ].pauseMin;
maxPause = level.sentrySettings[ self.sentryType ].pauseMax;
for ( ;; )
{
numShots = randomIntRange( minShots, maxShots + 1 );
for ( i = 0; i < numShots && !self.overheated; i++ )
{
self shootTurret();
self.heatLevel += fireTime;
wait ( fireTime );
}
wait ( randomFloatRange( minPause, maxPause ) );
}
}
sentry_burstFireStop()
{
self notify( "stop_shooting" );
}
sentry_heatMonitor()
{
self endon ( "death" );
fireTime = weaponFireTime( level.sentrySettings[ self.sentryType ].weaponInfo );
lastHeatLevel = 0;
lastFxTime = 0;
for ( ;; )
{
if ( self.heatLevel != lastHeatLevel )
wait ( fireTime );
else
self.heatLevel = max( 0, self.heatLevel - 0.05 );
if ( self.heatLevel > SENTRY_OVERHEAT_TIME )
{
self.overheated = true;
self thread PlayHeatFX();
while ( self.heatLevel )
{
self.heatLevel = max( 0, self.heatLevel - 0.1 );
wait ( 0.1 );
}
self.overheated = false;
self notify( "not_overheated" );
}
lastHeatLevel = self.heatLevel;
wait ( 0.05 );
}
}
playHeatFX()
{
self endon( "death" );
self endon( "not_overheated" );
level endon ( "game_ended" );
for( ;; )
{
playFxOnTag( getFx( "sentry_overheat_mp" ), self, "tag_flash" );
wait( SENTRY_FX_TIME );
}
}
sentry_beepSounds()
{
self endon( "death" );
level endon ( "game_ended" );
for ( ;; )
{
wait ( 3.0 );
if ( !isDefined( self.carriedBy ) )
self playSound( "sentry_gun_beep" );
}
}
+134
View File
@@ -0,0 +1,134 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
init()
{
level.killStreakFuncs["auto_shotgun"] = ::tryUseAutoShotgun;
level.killstreakSetupFuncs["auto_shotgun"] = ::shotgunSetup;
level.killStreakFuncs["thumper"] = ::tryUseThumper;
level.killstreakSetupFuncs["thumper"] = ::thumperSetup;
thread onPlayerConnect();
}
shotgunSetup()
{
self giveMaxAmmo( "aa12_mp" );
self thread saveWeaponAmmoOnDeath( "aa12_mp" );
}
tryUseAutoShotgun( lifeId )
{
self thread removeWeaponOnOutOfAmmo( "aa12_mp" );
return true;
}
thumperSetup()
{
self giveMaxAmmo( "m79_mp" );
self thread saveWeaponAmmoOnDeath( "m79_mp" );
}
tryUseThumper()
{
self thread removeWeaponOnOutOfAmmo( "m79_mp" );
return true;
}
onPlayerConnect()
{
for(;;)
{
level waittill( "connected", player );
player thread onPlayerSpawned();
}
}
onPlayerSpawned()
{
self endon( "disconnect" );
for(;;)
{
self waittill( "spawned_player" );
if ( !isDefined( self.pers["ksWeapon_clip_ammo"] ) || !isDefined( self.pers["ksWeapon_name"] ) )
continue;
weaponName = self.pers["ksWeapon_name"];
if ( isDefined( self.pers["killstreak"] ) && maps\mp\killstreaks\_killstreaks::getKillstreakWeapon( self.pers["killstreak"] ) != weaponName )
{
self.pers["ksWeapon_name"] = undefined;
self.pers["ksWeapon_clip_ammo"] = undefined;
self.pers["ksWeapon_stock_ammo"] = undefined;
continue;
}
self maps\mp\killstreaks\_killstreaks::giveKillstreakWeapon( weaponName );
self setWeaponAmmoStock( weaponName, self.pers["ksWeapon_stock_ammo"] );
self setWeaponAmmoClip( weaponName, self.pers["ksWeapon_clip_ammo"] );
self thread removeWeaponOnOutOfAmmo( weaponName );
self thread saveWeaponAmmoOnDeath( weaponName );
}
}
saveWeaponAmmoOnDeath( weaponName )
{
self endon ( "disconnect" );
self endon ( "got_killstreak" );
self notify( "saveWeaponAmmoOnDeath" );
self endon( "saveWeaponAmmoOnDeath" );
self.pers["ksWeapon_name"] = undefined;
self.pers["ksWeapon_clip_ammo"] = undefined;
self.pers["ksWeapon_stock_ammo"] = undefined;
self waittill ( "death" );
if ( !self hasWeapon( weaponName ) )
return;
self.pers["ksWeapon_name"] = weaponName;
self.pers["ksWeapon_clip_ammo"] = self getWeaponAmmoClip( weaponName );
self.pers["ksWeapon_stock_ammo"] = self getWeaponAmmoStock( weaponName );
}
removeWeaponOnOutOfAmmo( weaponName )
{
self endon ( "disconnect" );
self endon ( "death" );
self notify( weaponName + "_ammo_monitor" );
self endon( weaponName + "_ammo_monitor" );
while( 1 )
{
self waittill ( "end_firing" );
if ( self getCurrentWeapon() != weaponName )
continue;
total_ammo = self getWeaponAmmoClip( weaponName ) + self getWeaponAmmoStock( weaponName );
if ( total_ammo )
continue;
self takeWeapon( weaponName );
return;
}
}
+321
View File
@@ -0,0 +1,321 @@
#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;
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"];
otherTeam = level.otherTeam[myTeam];
if ( level.teamBased )
self thread EMP_JamTeam( otherTeam, 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_JamTeam( teamName, duration, delay )
{
level endon ( "game_ended" );
assert( teamName == "allies" || teamName == "axis" );
//wait ( delay );
thread teamPlayerCardSplash( "used_emp", self );
level notify ( "EMP_JamTeam" + teamName );
level endon ( "EMP_JamTeam" + teamName );
foreach ( player in level.players )
{
player playLocalSound( "emp_activate" );
if ( player.team != teamName )
continue;
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.teamEMPed[teamName] = true;
level notify ( "emp_update" );
level destroyActiveVehicles( self );
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( duration );
level.teamEMPed[teamName] = false;
foreach ( player in level.players )
{
if ( player.team != teamName )
continue;
if ( player _hasPerk( "specialty_localjammer" ) )
player RadarJamOn();
}
level notify ( "emp_update" );
}
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;
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;
if ( player _hasPerk( "specialty_localjammer" ) )
player RadarJamOn();
}
level.empPlayer = undefined;
level notify ( "emp_update" );
level notify ( "emp_ended" );
}
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, 16, 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, 16, 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 );
}
}
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+710
View File
@@ -0,0 +1,710 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
KILLSTREAK_STRING_TABLE = "mp/killstreakTable.csv";
init()
{
// &&1 Kill Streak!
precacheString( &"MP_KILLSTREAK_N" );
precacheString( &"MP_NUKE_ALREADY_INBOUND" );
precacheString( &"MP_UNAVILABLE_IN_LASTSTAND" );
precacheString( &"MP_UNAVAILABLE_WHEN_EMP" );
precacheString( &"MP_UNAVAILABLE_USING_TURRET" );
precacheString( &"MP_UNAVAILABLE_WHEN_INCAP" );
precacheString( &"MP_HELI_IN_QUEUE" );
initKillstreakData();
level.killstreakFuncs = [];
level.killstreakSetupFuncs = [];
level.killstreakWeapons = [];
level.killStreakMod = 0;
thread maps\mp\killstreaks\_ac130::init();
thread maps\mp\killstreaks\_remotemissile::init();
thread maps\mp\killstreaks\_uav::init();
thread maps\mp\killstreaks\_airstrike::init();
thread maps\mp\killstreaks\_airdrop::init();
thread maps\mp\killstreaks\_helicopter::init();
thread maps\mp\killstreaks\_autosentry::init();
thread maps\mp\killstreaks\_tank::init();
thread maps\mp\killstreaks\_emp::init();
thread maps\mp\killstreaks\_nuke::init();
level.killstreakRoundDelay = getIntProperty( "scr_game_killstreakdelay", 8 );
level thread onPlayerConnect();
}
initKillstreakData()
{
for ( i = 1; true; i++ )
{
retVal = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 1 );
if ( !isDefined( retVal ) || retVal == "" )
break;
streakRef = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 1 );
assert( streakRef != "" );
streakUseHint = tableLookupIString( KILLSTREAK_STRING_TABLE, 0, i, 6 );
assert( streakUseHint != &"" );
precacheString( streakUseHint );
streakEarnDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 8 );
assert( streakEarnDialog != "" );
game[ "dialog" ][ streakRef ] = streakEarnDialog;
streakAlliesUseDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 9 );
assert( streakAlliesUseDialog != "" );
game[ "dialog" ][ "allies_friendly_" + streakRef + "_inbound" ] = "use_" + streakAlliesUseDialog;
game[ "dialog" ][ "allies_enemy_" + streakRef + "_inbound" ] = "enemy_" + streakAlliesUseDialog;
streakAxisUseDialog = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 10 );
assert( streakAxisUseDialog != "" );
game[ "dialog" ][ "axis_friendly_" + streakRef + "_inbound" ] = "use_" + streakAxisUseDialog;
game[ "dialog" ][ "axis_enemy_" + streakRef + "_inbound" ] = "enemy_" + streakAxisUseDialog;
streakWeapon = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 12 );
precacheItem( streakWeapon );
streakPoints = int( tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 13 ) );
assert( streakPoints != 0 );
maps\mp\gametypes\_rank::registerScoreInfo( "killstreak_" + streakRef, streakPoints );
streakShader = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 14 );
precacheShader( streakShader );
streakShader = tableLookup( KILLSTREAK_STRING_TABLE, 0, i, 15 );
if ( streakShader != "" )
precacheShader( streakShader );
}
}
onPlayerConnect()
{
for ( ;; )
{
level waittill( "connected", player );
if( !isDefined ( player.pers[ "killstreaks" ] ) )
player.pers[ "killstreaks" ] = [];
if( !isDefined ( player.pers[ "kID" ] ) )
player.pers[ "kID" ] = 10;
if( !isDefined ( player.pers[ "kIDs_valid" ] ) )
player.pers[ "kIDs_valid" ] = [];
player.lifeId = 0;
if ( isDefined( player.pers["deaths"] ) )
player.lifeId = player.pers["deaths"];
player VisionSetMissilecamForPlayer( game["thermal_vision"] );
player thread onPlayerSpawned();
player thread onPlayerChangeKit();
}
}
onPlayerSpawned()
{
self endon( "disconnect" );
for ( ;; )
{
self waittill( "spawned_player" );
self thread killstreakUseWaiter();
self thread waitForChangeTeam();
self giveOwnedKillstreakItem( true );
}
}
onPlayerChangeKit()
{
self endon( "disconnect" );
for ( ;; )
{
self waittill( "changed_kit" );
self giveOwnedKillstreakItem();
}
}
waitForChangeTeam()
{
self endon ( "disconnect" );
self notify ( "waitForChangeTeam" );
self endon ( "waitForChangeTeam" );
for ( ;; )
{
self waittill ( "joined_team" );
clearKillstreaks();
}
}
isRideKillstreak( streakName )
{
switch( streakName )
{
case "helicopter_minigun":
case "helicopter_mk19":
case "ac130":
case "predator_missile":
return true;
default:
return false;
}
}
isCarryKillstreak( streakName )
{
switch( streakName )
{
case "sentry":
case "sentry_gl":
return true;
default:
return false;
}
}
deadlyKillstreak( streakName )
{
switch ( streakName )
{
case "predator_missile":
case "precision_airstrike":
case "harrier_airstrike":
//case "helicopter":
//case "helicopter_flares":
case "stealth_airstrike":
//case "helicopter_minigun":
case "ac130":
return true;
}
return false;
}
killstreakUsePressed()
{
streakName = self.pers["killstreaks"][0].streakName;
lifeId = self.pers["killstreaks"][0].lifeId;
isEarned = self.pers["killstreaks"][0].earned;
awardXp = self.pers["killstreaks"][0].awardXp;
kID = self.pers["killstreaks"][0].kID;
assert( isDefined( streakName ) );
assert( isDefined( level.killstreakFuncs[ streakName ] ) );
if ( !self isOnGround() && ( isRideKillstreak( streakName ) || isCarryKillstreak( streakName ) ) )
return ( false );
if ( self isUsingRemote() )
return ( false );
if ( isDefined( self.selectingLocation ) )
return ( false );
if ( deadlyKillstreak( streakName ) && level.killstreakRoundDelay && getGametypeNumLives() )
{
if ( level.gracePeriod - level.inGracePeriod < level.killstreakRoundDelay )
{
self iPrintLnBold( &"MP_UNAVAILABLE_FOR_N", (level.killstreakRoundDelay - (level.gracePeriod - level.inGracePeriod)) );
return ( false );
}
}
if ( (level.teamBased && level.teamEMPed[self.team]) || (!level.teamBased && isDefined( level.empPlayer ) && level.empPlayer != self) )
{
self iPrintLnBold( &"MP_UNAVAILABLE_WHEN_EMP" );
return ( false );
}
if ( self IsUsingTurret() && ( isRideKillstreak( streakName ) || isCarryKillstreak( streakName ) ) )
{
self iPrintLnBold( &"MP_UNAVAILABLE_USING_TURRET" );
return ( false );
}
if ( isDefined( self.lastStand ) && isRideKillstreak( streakName ) )
{
self iPrintLnBold( &"MP_UNAVILABLE_IN_LASTSTAND" );
return ( false );
}
if ( !self isWeaponEnabled() )
return ( false );
if ( streakName == "airdrop" || streakName == "airdrop_sentry_minigun" || streakName == "airdrop_mega" )
{
if ( !self [[ level.killstreakFuncs[ streakName ] ]]( lifeId, kID ) )
return ( false );
}
else
{
if ( !self [[ level.killstreakFuncs[ streakName ] ]]( lifeId ) )
return ( false );
}
self usedKillstreak( streakName, awardXp );
self shuffleKillStreaksFILO( streakName );
self giveOwnedKillstreakItem();
return ( true );
}
//this overwrites killstreak at index 0 and decrements all other killstreaks (FCLS style)
shuffleKillStreaksFILO( streakName )
{
self _setActionSlot( 4, "" );
arraySize = self.pers["killstreaks"].size;
streakIndex = -1;
for ( i = 0; i < arraySize; i++ )
{
if ( self.pers["killstreaks"][i].streakName != streakName )
continue;
streakIndex = i;
break;
}
assert( streakIndex >= 0 );
self.pers["killstreaks"][streakIndex] = undefined;
for( i = streakIndex + 1; i < arraySize; i++ )
{
if ( i == arraySize - 1 )
{
self.pers["killstreaks"][i-1] = self.pers["killstreaks"][i];
self.pers["killstreaks"][i] = undefined;
}
else
{
self.pers["killstreaks"][i-1] = self.pers["killstreaks"][i];
}
}
}
usedKillstreak( streakName, awardXp )
{
self playLocalSound( "weap_c4detpack_trigger_plr" );
if ( awardXp )
self thread [[ level.onXPEvent ]]( "killstreak_" + streakName );
self thread maps\mp\gametypes\_missions::useHardpoint( streakName );
awardref = maps\mp\_awards::getKillstreakAwardRef( streakName );
if ( isDefined( awardref ) )
self thread incPlayerStat( awardref, 1 );
team = self.team;
if ( level.teamBased )
{
thread leaderDialog( team + "_friendly_" + streakName + "_inbound", team );
if ( getKillstreakInformEnemy( streakName ) )
thread leaderDialog( team + "_enemy_" + streakName + "_inbound", level.otherTeam[ team ] );
}
else
{
self thread leaderDialogOnPlayer( team + "_friendly_" + streakName + "_inbound" );
if ( getKillstreakInformEnemy( streakName ) )
{
excludeList[0] = self;
thread leaderDialog( team + "_enemy_" + streakName + "_inbound", undefined, undefined, excludeList );
}
}
}
clearKillstreaks()
{
foreach ( index, streakStruct in self.pers["killstreaks"] )
self.pers["killstreaks"][index] = undefined;
}
getFirstPrimaryWeapon()
{
weaponsList = self getWeaponsListPrimaries();
assert ( isDefined( weaponsList[0] ) );
assert ( !isKillstreakWeapon( weaponsList[0] ) );
if ( weaponsList[0] == "onemanarmy_mp" )
{
assert ( isDefined( weaponsList[1] ) );
assert ( !isKillstreakWeapon( weaponsList[1] ) );
return weaponsList[1];
}
return weaponsList[0];
}
killstreakUseWaiter()
{
self endon( "disconnect" );
self endon( "finish_death" );
level endon( "game_ended" );
self.lastKillStreak = 0;
if ( !isDefined( self.pers["lastEarnedStreak"] ) )
self.pers["lastEarnedStreak"] = undefined;
self thread finishDeathWaiter();
for ( ;; )
{
self waittill ( "weapon_change", newWeapon );
if ( !isAlive( self ) )
continue;
if ( !isDefined( self.pers["killstreaks"][0] ) )
continue;
if ( newWeapon != getKillstreakWeapon( self.pers["killstreaks"][0].streakName ) )
continue;
waittillframeend;
streakName = self.pers["killstreaks"][0].streakName;
result = self killstreakUsePressed();
//no force switching weapon for ridable killstreaks
if ( !isRideKillstreak( streakName ) || !result )
{
if ( !self hasWeapon( self getLastWeapon() ) )
self switchToWeapon( self getFirstPrimaryWeapon() );
else
self switchToWeapon( self getLastWeapon() );
}
// give time to switch to the near weapon; when the weapon is none (such as during a "disableWeapon()" period
// re-enabling the weapon immediately does a "weapon_change" to the killstreak weapon we just used. In the case that
// we have two of that killstreak, it immediately uses the second one
if ( self getCurrentWeapon() == "none" )
{
while ( self getCurrentWeapon() == "none" )
wait ( 0.05 );
waittillframeend;
}
}
}
finishDeathWaiter()
{
self endon ( "disconnect" );
self waittill ( "death" );
wait ( 0.05 );
self notify ( "finish_death" );
self.pers["lastEarnedStreak"] = undefined;
}
checkKillstreakReward( streakCount )
{
self notify( "got_killstreak", streakCount );
maxVal = 0;
killStreaks = [];
foreach ( streakVal, streakName in self.killStreaks )
{
killStreaks[streakName] = streakVal;
if ( streakVal > maxVal )
maxVal = streakVal;
}
foreach ( streakVal, streakName in self.killStreaks )
{
actualVal = streakVal + level.killStreakMod;
if ( actualVal > streakCount )
break;
if ( isDefined( self.pers["lastEarnedStreak"] ) && killStreaks[streakName] <= killStreaks[self.pers["lastEarnedStreak"]] )
continue;
if ( isSubStr( streakName, "-rollover" ) )
{
continue;
/*
if ( game["defcon"] > 2 )
{
self.pers["lastEarnedStreak"] = streakName;
continue;
}
useStreakName = strTok( streakName, "-" )[0];
*/
}
else
{
useStreakName = streakName;
}
if ( self tryGiveKillstreak( useStreakName, int(max( actualVal, streakCount )) ) )
{
self thread killstreakEarned( useStreakName );
self.pers["lastEarnedStreak"] = streakName;
}
}
}
killstreakEarned( streakName )
{
if ( self getPlayerData( "killstreaks", 0 ) == streakName )
{
self.firstKillstreakEarned = getTime();
}
else if ( self getPlayerData( "killstreaks", 2 ) == streakName && isDefined( self.firstKillstreakEarned ) )
{
if ( getTime() - self.firstKillstreakEarned < 20000 )
self thread maps\mp\gametypes\_missions::genericChallenge( "wargasm" );
}
}
rewardNotify( streakName, streakVal )
{
self endon( "disconnect" );
self maps\mp\gametypes\_hud_message::killstreakSplashNotify( streakName, streakVal );
}
tryGiveKillstreak( streakName, streakVal )
{
level notify ( "gave_killstreak", streakName );
if ( !level.gameEnded )
self thread rewardNotify( streakName, streakVal );
self giveKillstreak( streakName, streakVal, true );
return true;
}
giveKillstreak( streakName, isEarned, awardXp, owner )
{
self endon ( "disconnect" );
weapon = getKillstreakWeapon( streakName );
self giveKillstreakWeapon( weapon );
// shuffle existing killstreaks up a notch
for( i = self.pers["killstreaks"].size; i >= 0; i-- )
self.pers["killstreaks"][i + 1] = self.pers["killstreaks"][i];
self.pers["killstreaks"][0] = spawnStruct();
self.pers["killstreaks"][0].streakName = streakName;
self.pers["killstreaks"][0].earned = isDefined( isEarned ) && isEarned;
self.pers["killstreaks"][0].awardxp = isDefined( awardXp ) && awardXp;
self.pers["killstreaks"][0].owner = owner;
self.pers["killstreaks"][0].kID = self.pers["kID"];
self.pers["kIDs_valid"][self.pers["kID"]] = true;
self.pers["kID"]++;
if ( !self.pers["killstreaks"][0].earned )
self.pers["killstreaks"][0].lifeId = -1;
else
self.pers["killstreaks"][0].lifeId = self.pers["deaths"];
// probably obsolete unless we bring back the autoshotty
if ( isdefined( level.killstreakSetupFuncs[ streakName ] ) )
self [[ level.killstreakSetupFuncs[ streakName ] ]]();
if ( isDefined( isEarned ) && isEarned && isDefined( awardXp ) && awardXp )
self notify( "received_earned_killstreak" );
}
giveKillstreakWeapon( weapon )
{
weaponList = self getWeaponsListItems();
foreach ( item in weaponList )
{
if ( !isSubStr( item, "killstreak" ) )
continue;
if ( self getCurrentWeapon() == item )
continue;
self takeWeapon( item );
}
self _giveWeapon( weapon, 0 );
self _setActionSlot( 4, "weapon", weapon );
}
getStreakCost( streakName )
{
return int( tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 4 ) );
}
getKillstreakHint( streakName )
{
return tableLookupIString( KILLSTREAK_STRING_TABLE, 1, streakName, 6 );
}
getKillstreakInformEnemy( streakName )
{
return int( tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 11 ) );
}
getKillstreakSound( streakName )
{
return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 7 );
}
getKillstreakDialog( streakName )
{
return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 8 );
}
getKillstreakWeapon( streakName )
{
return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 12 );
}
getKillstreakIcon( streakName )
{
return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 14 );
}
getKillstreakCrateIcon( streakName )
{
return tableLookup( KILLSTREAK_STRING_TABLE, 1, streakName, 15 );
}
giveOwnedKillstreakItem( skipDialog )
{
if ( !isDefined( self.pers["killstreaks"][0] ) )
return;
streakName = self.pers["killstreaks"][0].streakName;
weapon = getKillstreakWeapon( streakName );
self giveKillstreakWeapon( weapon );
if ( !isDefined( skipDialog ) && !level.inGracePeriod )
self leaderDialogOnPlayer( streakName, "killstreak_earned" );
}
initRideKillstreak()
{
self _disableUsability();
result = self initRideKillstreak_internal();
if ( isDefined( self ) )
self _enableUsability();
return result;
}
initRideKillstreak_internal()
{
laptopWait = self waittill_any_timeout( 1.0, "disconnect", "death", "weapon_switch_started" );
if ( laptopWait == "weapon_switch_started" )
return ( "fail" );
if ( !isAlive( self ) )
return "fail";
if ( laptopWait == "disconnect" || laptopWait == "death" )
{
if ( laptopWait == "disconnect" )
return ( "disconnect" );
if ( self.team == "spectator" )
return "fail";
return ( "success" );
}
if ( self isEMPed() || self isNuked() )
{
return ( "fail" );
}
self VisionSetNakedForPlayer( "black_bw", 0.75 );
blackOutWait = self waittill_any_timeout( 0.80, "disconnect", "death" );
if ( blackOutWait != "disconnect" )
{
self thread clearRideIntro( 1.0 );
if ( self.team == "spectator" )
return "fail";
}
if ( !isAlive( self ) )
return "fail";
if ( self isEMPed() || self isNuked() )
return "fail";
if ( blackOutWait == "disconnect" )
return ( "disconnect" );
else
return ( "success" );
}
clearRideIntro( delay )
{
self endon( "disconnect" );
if ( isDefined( delay ) )
wait( delay );
//self freezeControlsWrapper( false );
if ( !isDefined( level.nukeVisionInProgress ) )
self VisionSetNakedForPlayer( getDvar( "mapname" ), 0 );
}
+489
View File
@@ -0,0 +1,489 @@
#include maps\mp\_utility;
#include common_scripts\utility;
/*******************************************************************
// _littleBird.gsc
//
// Holds all the littlebird specific functions
//
// Jordan Hirsh Jan. 6th 2009
********************************************************************/
init()
{
precacheString( &"MP_CIVILIAN_AIR_TRAFFIC" );
precacheString( &"MP_AIR_SPACE_TOO_CROWDED" );
return;
//precacheString( &"MP_WAR_AIRSTRIKE_INBOUND_NEAR_YOUR_POSITION" );
//precacheString( &"MP_WAR_AIRSTRIKE_INBOUND" );
//precacheTurret( "minigun_littlebird_mp" );
//precacheModel( "vehicle_little_bird_minigun_left" );
//precacheModel( "vehicle_little_bird_minigun_right" );
//level.attackLB = [];
//level.lbStrike = 0;
//level.killStreakFuncs["littlebird_support"] = ::tryUseLbStrike;
}
tryUseLbStrike( lifeId )
{
if ( isDefined( level.civilianJetFlyBy ) )
{
self iPrintLnBold( &"MP_CIVILIAN_AIR_TRAFFIC" );
return false;
}
if ( self isUsingRemote() )
{
return false;
}
if ( level.lbStrike >= 1 )
{
self iPrintLnBold( &"MP_AIR_SPACE_TOO_CROWDED" );
return false;
}
result = self selectLbStrikeLocation( lifeId );
if ( !isDefined( result ) || !result )
return false;
level.lbStrike++;
return true;
}
startLBStrike( lifeId, origin, owner, team, yawDir )
{
while ( isDefined( level.airstrikeInProgress ) )
{
level waittill ( "begin_airstrike" );
}
level.airstrikeInProgress = true;
num = 17 + randomint(3);
trace = bullettrace(origin, origin + (0,0,-1000000), false, undefined);
targetpos = trace["position"];
//yaw = getBestLbDirection( targetpos );
//yaw = 90;
yaw = yawDir;
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 ) )
{
if ( playerteam == team )
player iprintln( &"MP_WAR_AIRSTRIKE_INBOUND", owner );
}
}
}
// buffer between airstrikes
level.airstrikeInProgress = undefined;
owner notify ( "begin_airstrike" );
level notify ( "begin_airstrike" );
if ( !isDefined( owner ) )
return;
callStrike( lifeId, owner, targetpos, yaw );
}
clearProgress( delay )
{
if( !isDefined( delay ) )
delay = 0;
wait ( delay );
level.lbStrike = 0;
}
doLbStrike( lifeId, owner, requiredDeathCount, coord, startPoint, endPoint, direction )
{
self endon( "death" );
if ( !isDefined( owner ) )
return;
lb = spawnAttackLittleBird( owner, startPoint, endPoint, coord );
lb.lifeId = lifeId;
lb thread watchDeath();
lb thread waitTillGone();
lb endon( "death" );
totalDist = Distance2d( startPoint, coord );
midTime = ( totalDist / lb.speed ) / 2 * .1 + 2.5;
assert ( isDefined( lb ) );
lb SetMaxPitchRoll( 45, 45 );
//moving to end point
lb setVehGoalPos( endPoint, 1 );
wait( midTime - 1 );
//slowing down and firing
lb Vehicle_SetSpeed( 45, 60 );
wait( 1 );
lb SetMaxPitchRoll( 200, 200 );
wait ( 5 );
lb thread startLbFiring();
wait ( 7 );
//stops firing and turns around
lb notify ( "stopFiring" );
lb Vehicle_SetSpeed( 75, 60 );
lb SetMaxPitchRoll( 65, 65 );
wait(2.5);
lb setVehGoalPos( startPoint, 1 );
wait ( 4 );
lb SetMaxPitchRoll( 180, 180 );
wait ( .75 );
//slows down firing opposite direction
lb Vehicle_SetSpeed( 45, 60 );
lb thread startLbFiring();
wait ( 6 );
//off into the sunset
lb Vehicle_SetSpeed( lb.speed, 60 );
lb notify ( "stopFiring" );
lb SetMaxPitchRoll( 75, 180 );
lb waittill ( "goal" );
lb notify( "gone" );
lb delete();
}
waitTillGone()
{
self waittill( "gone" );
clearProgress( 0 );
}
// spawn helicopter at a start node and monitors it
spawnAttackLittleBird( owner, pathStart, pathGoal, coord )
{
forward = vectorToAngles( pathGoal - pathStart );
lb = spawnHelicopter( owner, pathStart, forward, "littlebird_mp" , "vehicle_little_bird_armed" );
if ( !isDefined( lb ) )
return;
lb.speed = 400;
lb.health = 350;
lb setCanDamage( true );
lb.owner = owner;
lb.team = owner.team;
lb SetMaxPitchRoll( 45, 45 );
lb Vehicle_SetSpeed( lb.speed, 60 );
lb.damageCallback = ::Callback_VehicleDamage;
mgTurret1 = spawnTurret( "misc_turret", lb.origin, "minigun_littlebird_mp" );
mgTurret1 linkTo( lb, "tag_minigun_attach_right", (0,0,0), (0,0,0) );
mgTurret1 setModel( "vehicle_little_bird_minigun_right" );
mgTurret1.angles = lb.angles;
mgTurret1.owner = lb.owner;
mgTurret1.team = mgTurret1.owner.team;
mgTurret1 SetPlayerSpread( .65 );
mgTurret1 makeTurretInoperable();
lb.mgTurret1 = mgTurret1;
lb.mgTurret1 SetDefaultDropPitch( 0 );
mgTurret2 = spawnTurret( "misc_turret", lb.origin, "minigun_littlebird_mp" );
mgTurret2 linkTo( lb, "tag_minigun_attach_left", (0,0,0), (0,0,0) );
mgTurret2 setModel( "vehicle_little_bird_minigun_right" );
mgTurret2 SetPlayerSpread( .65 );
mgTurret2.angles = lb.angles;
mgTurret2.owner = lb.owner;
mgTurret2.team = mgTurret2.owner.team;
mgTurret2 makeTurretInoperable();
lb.mgTurret2 = mgTurret2;
lb.mgTurret2 SetDefaultDropPitch( 0 );
level.littlebird[level.littlebird.size] = lb;
return lb;
}
startLbFiring( )
{
self endon( "gone" );
self endon( "death" );
self endon( "stopFiring" );
i = 0;
for( ;; )
{
self.mgTurret1 ShootTurret();
self.mgTurret2 ShootTurret();
wait ( 0.05 );
}
}
getBestLbDirection( hitpos )
{
//if ( !self.precisionAirstrike )
// return randomFloat( 360 );
checkPitch = -25;
numChecks = 15;
startpos = hitpos + (0,0,64);
bestangle = randomfloat( 360 );
bestanglefrac = 0;
fullTraceResults = [];
for ( i = 0; i < numChecks; i++ )
{
yaw = ((i * 1.0 + randomfloat(1)) / numChecks) * 360.0;
angle = (checkPitch, yaw + 180, 0);
dir = anglesToForward( angle );
endpos = startpos + dir * 1500;
trace = bullettrace( startpos, endpos, false, undefined );
if ( trace["fraction"] > bestanglefrac )
{
bestanglefrac = trace["fraction"];
bestangle = yaw;
if ( trace["fraction"] >= 1 )
fullTraceResults[ fullTraceResults.size ] = yaw;
}
if ( i % 3 == 0 )
wait .05;
}
if ( fullTraceResults.size > 0 )
return fullTraceResults[ randomint( fullTraceResults.size ) ];
return bestangle;
}
callStrike( lifeId, owner, coord, yaw )
{
// Get starting and ending point for the plane
direction = ( 0, yaw, 0 );
planeHalfDistance = 24000;
planeFlyHeight = 850;
planeFlySpeed = 7000;
if ( isdefined( level.airstrikeHeightScale ) )
planeFlyHeight *= level.airstrikeHeightScale;
startPoint = coord + vector_multiply( anglestoforward( direction ), -1 * planeHalfDistance );
startPoint += ( 0, 0, planeFlyHeight );
endPoint = coord + vector_multiply( anglestoforward( direction ), planeHalfDistance );
endPoint += ( 0, 0, planeFlyHeight );
owner endon("disconnect");
requiredDeathCount = owner.lifeId;
level thread doLbStrike( lifeId, owner, requiredDeathCount, coord, startPoint, endPoint, direction );
}
waitForLbStrikeCancel()
{
self waittill( "cancel_location" );
self setblurforplayer( 0, 0.3 );
}
selectLbStrikeLocation( lifeId )
{
self setClientDvar( "ui_selecting_location", "1");
self beginLocationSelection( "map_artillery_selector", true, 500 );
self.selectingLocation = true;
self setblurforplayer( 10.3, 0.3 );
self thread waitForLbStrikeCancel();
self thread endSelectionOn( "cancel_location" );
self thread endSelectionOn( "death" );
self thread endSelectionOn( "disconnect" );
self thread endSelectionOn( "used" );
self thread endSelectionOnGameEnd();
self endon( "stop_location_selection" );
// wait for the selection. randomize the yaw if we ever stop doing a precision selection
self waittill( "confirm_location", location, locationYaw);
self setblurforplayer( 0, 0.3 );
self thread finishLbStrikeUsage( lifeId, location, ::useLbStrike, locationYaw );
return true;
}
finishLbStrikeUsage( lifeId, location, usedCallback, locationYaw )
{
self notify( "used" );
wait ( 0.05 );
self thread stopLbStrikeLocationSelection( false );
self thread [[usedCallback]]( lifeId, location, locationYaw );
return true;
}
endSelectionOn( waitfor )
{
self endon( "stop_location_selection" );
self waittill( waitfor );
self thread stopLbStrikeLocationSelection( (waitfor == "disconnect") );
}
endSelectionOnGameEnd()
{
self endon( "stop_location_selection" );
level waittill( "game_ended" );
self thread stopLbStrikeLocationSelection( false );
}
stopLbStrikeLocationSelection( disconnected )
{
if ( !disconnected )
{
self setblurforplayer( 0, 0.3 );
self endLocationSelection();
self.selectingLocation = undefined;
}
self notify( "stop_location_selection" );
}
useLbStrike( lifeId, pos, yawDir )
{
// find underside of top of skybox
trace = bullettrace( level.mapCenter + (0,0,1000000), level.mapCenter, false, undefined );
pos = (pos[0], pos[1], trace["position"][2] - 514);
thread startLBStrike( lifeId, pos, self, self.pers["team"], yawDir );
}
Callback_VehicleDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName )
{
if ( ( attacker == self || ( isDefined( attacker.pers ) && attacker.pers["team"] == self.team ) ) && ( attacker != self.owner || meansOfDeath == "MOD_MELEE" ) )
return;
self Vehicle_FinishDamage( inflictor, attacker, damage, dFlags, meansOfDeath, weapon, point, dir, hitLoc, timeOffset, modelIndex, partName );
}
watchDeath()
{
self endon( "gone" );
self waittill( "death" );
self thread heliDestroyed();
level.littleBirds--;
clearProgress( 0.05 );
return;
}
heliDestroyed()
{
self endon( "gone" );
if (! isDefined(self) )
return;
//self trimActiveBirdList();
self Vehicle_SetSpeed( 25, 5 );
self thread lbSpin( RandomIntRange(180, 220) );
wait( RandomFloatRange( .5, 1.5 ) );
lbExplode();
}
lbExplode()
{
forward = ( self.origin + ( 0, 0, 1 ) ) - self.origin;
playfx ( level.chopper_fx["explode"]["air_death"], self.origin, forward );
deathAngles = self getTagAngles( "tag_deathfx" );
playFx( level.chopper_fx["explode"]["air_death"]["littlebird"], self getTagOrigin( "tag_deathfx" ), anglesToForward( deathAngles ), anglesToUp( deathAngles ) );
self playSound( "cobra_helicopter_crash" );
self notify ( "explode" );
if ( isDefined( self.mgTurret1 ) )
self.mgTurret1 delete();
if ( isDefined( self.mgTurret2 ) )
self.mgTurret2 delete();
self clearProgress( 0 );
self delete();
}
lbSpin( speed )
{
self endon( "explode" );
// tail explosion that caused the spinning
playfxontag( level.chopper_fx["explode"]["medium"], self, "tail_rotor_jnt" );
self thread trail_fx( level.chopper_fx["smoke"]["trail"], "tail_rotor_jnt", "stop tail smoke" );
self setyawspeed( speed, speed, speed );
while ( isdefined( self ) )
{
self settargetyaw( self.angles[1]+(speed*0.9) );
wait ( 1 );
}
}
trail_fx( trail_fx, trail_tag, stop_notify )
{
// only one instance allowed
self notify( stop_notify );
self endon( stop_notify );
self endon( "death" );
for ( ;; )
{
playfxontag( trail_fx, self, trail_tag );
wait( 0.05 );
}
}
+316
View 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" );
}
+379
View File
@@ -0,0 +1,379 @@
#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.missilesForSightTraces = [];
}
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 );
}
File diff suppressed because it is too large. Load diff
+638
View File
@@ -0,0 +1,638 @@
#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" );
precacheModel( "vehicle_uav_static_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;
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"] = [];
}
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" );
}
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" );
}
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.teamBased )
{
updateTeamUAVStatus( "allies" );
updateTeamUAVStatus( "axis" );
}
else
{
updatePlayersUAVStatus();
}
}
}
updateTeamUAVStatus( team )
{
activeUAVs = level.activeUAVs[team];
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;
player.radarMode = "normal_radar";
continue;
}
if ( activeUAVs > 1 )
player.radarMode = "fast_radar";
else
player.radarMode = "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;
player.radarMode = level.radarMode[player.team];
}
}
usePlayerUAV( doubleUAV, useTime )
{
level endon("game_ended");
self endon("disconnect");
self notify ( "usePlayerUAV" );
self endon ( "usePlayerUAV" );
if ( doubleUAV )
self.radarMode = "fast_radar";
else
self.radarMode = "normal_radar";
self.hasRadar = true;
wait ( useTime );
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]--;
}
}