572 lines
15 KiB
Plaintext
572 lines
15 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include maps\mp\gametypes\_hud_util;
|
|
#include common_scripts\utility;
|
|
|
|
|
|
//============================================
|
|
// constants
|
|
//============================================
|
|
CONST_UPLINK_WEAPON = "killstreak_uplink_mp";
|
|
CONST_UPLINK_TIME = 30;
|
|
CONST_UPLINK_MIN = 0;
|
|
CONST_EYES_ON = 1;
|
|
CONST_UPLINK_FULL_RADAR = 2;
|
|
CONST_UPLINK_FAST_PING = 3;
|
|
CONST_DIRECTIONAL = 4;
|
|
CONST_UPLINK_MAX = 4;
|
|
CONST_FAST_SWEEP = "fast_radar";
|
|
CONST_NORMAL_SWEEP = "normal_radar";
|
|
CONST_HEAD_ICON_OFFSET = 42;
|
|
CONST_EMP_VFX = "emp_stun";
|
|
CONST_EMP_VFX_TAG = "tag_origin";
|
|
|
|
//============================================
|
|
// init
|
|
//============================================
|
|
init()
|
|
{
|
|
level.uplinks = [];
|
|
level.killstreakFuncs["uplink"] = ::tryUseUpLink;
|
|
level.killstreakFuncs["uplink_support"] = ::tryUseUpLink;
|
|
|
|
level.comExpFuncs = [];
|
|
level.comExpFuncs[ "giveComExpBenefits" ] = ::giveComExpBenefits;
|
|
level.comExpFuncs[ "removeComExpBenefits" ] = ::removeComExpBenefits;
|
|
level.comExpFuncs[ "getRadarStrengthForTeam" ] = ::getRadarStrengthForTeam;
|
|
level.comExpFuncs[ "getRadarStrengthForPlayer" ] = ::getRadarStrengthForPlayer;
|
|
|
|
unblockTeamRadar( "axis" );
|
|
unblockTeamRadar( "allies" );
|
|
|
|
level thread upLinkTracker();
|
|
level thread uplinkUpdateEyesOn();
|
|
|
|
config = spawnStruct();
|
|
config.streakName = "uplink";
|
|
config.weaponInfo = "ims_projectile_mp";
|
|
config.modelBase = "mp_satcom";
|
|
// config.modelDestroyed = "placeable_barrier_destroyed";
|
|
config.modelPlacement = "mp_satcom_obj";
|
|
config.modelPlacementFailed = "mp_satcom_obj_red";
|
|
config.modelBombSquad = "mp_satcom_bombsquad";
|
|
config.hintString = &"KILLSTREAKS_HINTS_UPLINK_PICKUP";
|
|
config.placeString = &"KILLSTREAKS_HINTS_UPLINK_PLACE";
|
|
config.cannotPlaceString = &"KILLSTREAKS_HINTS_UPLINK_CANNOT_PLACE";
|
|
config.headIconHeight = CONST_HEAD_ICON_OFFSET;
|
|
config.splashName = "used_uplink";
|
|
config.lifeSpan = CONST_UPLINK_TIME;
|
|
// config.goneVO = "satcom_gone";
|
|
config.maxHealth = 500;
|
|
config.allowMeleeDamage = true;
|
|
config.allowEmpDamage = true;
|
|
config.damageFeedback = "trophy";
|
|
config.xpPopup = "destroyed_uplink";
|
|
config.destroyedVO = "satcom_destroyed";
|
|
//config.onCreateDelegate = ::createObject;
|
|
config.placementHeightTolerance = 30.0;
|
|
config.placementRadius = 16.0;
|
|
config.placementOffsetZ = 16;
|
|
config.onPlacedDelegate = ::onPlaced;
|
|
config.onCarriedDelegate = ::onCarried;
|
|
config.placedSfx = "mp_killstreak_satcom_deploy";
|
|
config.activeSfx = "mp_killstreak_satcom_loop";
|
|
config.onMovingPlatformCollision = ::uplink_override_moving_platform_death;
|
|
// config.onDamagedDelegate = ::onDamaged;
|
|
config.onDeathDelegate = ::onDeath;
|
|
config.onDestroyedDelegate = ::onDestroyed; // when killed by a player
|
|
config.deathVfx = loadfx( "vfx/gameplay/mp/killstreaks/vfx_ballistic_vest_death" );
|
|
// config.onDeactivateDelegate = ::onDeactivated;
|
|
// config.onActivateDelegate = ::onActivated;
|
|
|
|
level.placeableConfigs[ "uplink" ] = config;
|
|
level.placeableConfigs[ "uplink_support" ] = config;
|
|
}
|
|
|
|
|
|
//============================================
|
|
// upLinkTracker
|
|
//============================================
|
|
upLinkTracker()
|
|
{
|
|
level endon ( "game_ended" );
|
|
|
|
while( true )
|
|
{
|
|
level waittill( "update_uplink" );
|
|
level childthread updateAllUplinkThreads();
|
|
}
|
|
}
|
|
|
|
// 2013-08-27 wallace: I wonder if it would be ok to just update the uplink strength for a particular player/team on notify
|
|
// since the uplinks know who they belong to
|
|
updateAllUplinkThreads()
|
|
{
|
|
self notify("updateAllUplinkThreads");
|
|
self endon("updateAllUplinkThreads");
|
|
|
|
level childthread comExpNotifyWatcher();
|
|
|
|
if( level.teamBased )
|
|
{
|
|
level childthread updateTeamUpLink( "axis" );
|
|
level childthread updateTeamUpLink( "allies" );
|
|
}
|
|
else
|
|
{
|
|
level childthread updatePlayerUpLink();
|
|
}
|
|
|
|
// Update the the UpLink for Com Specialist players
|
|
level childthread updateComExpUpLink();
|
|
}
|
|
|
|
comExpNotifyWatcher()
|
|
{
|
|
// Guarantee that the previous update functions have finished before we proceed into updating com exp
|
|
teamsFinished = [];
|
|
|
|
if ( !level.teamBased )
|
|
level waittill ( "radar_status_change_players" );
|
|
else
|
|
{
|
|
while ( teamsFinished.size < 2 )
|
|
{
|
|
level waittill ( "radar_status_change", team );
|
|
teamsFinished[ teamsFinished.size ] = team;
|
|
}
|
|
}
|
|
|
|
level notify ( "start_com_exp" );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// updateTeamUpLink
|
|
//============================================
|
|
updateTeamUpLink( team )
|
|
{
|
|
currentStrengthForTeam = getRadarStrengthForTeam( team );
|
|
shouldBeEyesOn = ( currentStrengthForTeam == CONST_EYES_ON );
|
|
shouldBeFullRadar = ( currentStrengthForTeam >= CONST_UPLINK_FULL_RADAR );
|
|
shouldBeFastSweep = ( currentStrengthForTeam >= CONST_UPLINK_FAST_PING );
|
|
shouldBeDirectional = ( currentStrengthForTeam >= CONST_DIRECTIONAL );
|
|
|
|
if( shouldBeFullRadar )
|
|
{
|
|
unblockTeamRadar( team );
|
|
}
|
|
|
|
if( shouldBeFastSweep )
|
|
{
|
|
level.radarMode[team] = CONST_FAST_SWEEP;
|
|
}
|
|
else
|
|
{
|
|
level.radarMode[team] = CONST_NORMAL_SWEEP;
|
|
}
|
|
|
|
foreach( player in level.participants )
|
|
{
|
|
if ( !IsDefined(player) )
|
|
continue;
|
|
|
|
if( player.team != team )
|
|
continue;
|
|
|
|
player.shouldBeEyesOn = shouldBeEyesOn;
|
|
player SetEyesOnUplinkEnabled( shouldBeEyesOn );
|
|
player.radarMode = level.radarMode[player.team];
|
|
player.radarShowEnemyDirection = shouldBeDirectional;
|
|
player updateSatcomActiveOmnvar( team );
|
|
|
|
wait(0.05); // Setting all these player variables can get expensive, so spread it out over multiple frames
|
|
}
|
|
|
|
setTeamRadar( team, shouldBeFullRadar );
|
|
level notify( "radar_status_change", team );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// updatePlayerUpLink
|
|
//============================================
|
|
updatePlayerUpLink()
|
|
{
|
|
foreach ( player in level.participants )
|
|
{
|
|
if ( !IsDefined(player) )
|
|
continue;
|
|
|
|
currentStrengthForSelf = getRadarStrengthForPlayer( player );
|
|
setPlayerRadarEffect( player, currentStrengthForSelf );
|
|
player updateSatcomActiveOmnvar();
|
|
|
|
wait(0.05); // Setting all these player variables can get expensive, so spread it out over multiple frames
|
|
}
|
|
|
|
level notify( "radar_status_change_players" );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// updateComExpUpLink
|
|
//============================================
|
|
updateComExpUpLink()
|
|
{
|
|
level waittill ( "start_com_exp" );
|
|
|
|
foreach ( player in level.participants )
|
|
{
|
|
if ( !IsDefined(player) )
|
|
continue;
|
|
|
|
player giveComExpBenefits();
|
|
|
|
wait(0.05); // Setting all these player variables can get expensive, so spread it out over multiple frames
|
|
}
|
|
}
|
|
|
|
// give/remove ComExpBenefits
|
|
// encapsulate the innerworkings of uplink system for the perk's set/unset functions
|
|
giveComExpBenefits() // self == player
|
|
{
|
|
if( ( self _hasPerk( "specialty_comexp" ) ) )
|
|
{
|
|
radarStrength = getRadarStrengthForComExp( self );
|
|
setPlayerRadarEffect( self, radarStrength );
|
|
self updateSatcomActiveOmnvar();
|
|
}
|
|
}
|
|
|
|
// since multiple functions are trying to set the ui_satcom_active omnvar, I've made it one function that will handle the wiretap perk functionality
|
|
// this will make sure we always get it right and get the correct amount of radar
|
|
updateSatcomActiveOmnvar( team ) // self == player
|
|
{
|
|
radarStrength = 0;
|
|
if( IsDefined( team ) )
|
|
radarStrength = getRadarStrengthForTeam( team );
|
|
else
|
|
radarStrength = getRadarStrengthForPlayer( self );
|
|
|
|
if( self _hasPerk( "specialty_comexp" ) )
|
|
radarStrength = getRadarStrengthForComExp( self );
|
|
|
|
if( radarStrength > CONST_UPLINK_MIN )
|
|
self SetClientOmnvar( "ui_satcom_active", true );
|
|
else
|
|
self SetClientOmnvar( "ui_satcom_active", false );
|
|
}
|
|
|
|
removeComExpBenefits() // self == player
|
|
{
|
|
// mainly for clearing out radarMode, the other stuff will get set by the appropriate update function
|
|
self.shouldBeEyesOn = false;
|
|
self SetEyesOnUplinkEnabled( false );
|
|
self.radarShowEnemyDirection = false;
|
|
self.radarMode = CONST_NORMAL_SWEEP;
|
|
self.hasRadar = false;
|
|
self.isRadarBlocked = false;
|
|
}
|
|
|
|
setPlayerRadarEffect( player, radarStrength )
|
|
{
|
|
shouldBeEyesOn = ( radarStrength == CONST_EYES_ON );
|
|
shouldBeFullRadar = ( radarStrength >= CONST_UPLINK_FULL_RADAR );
|
|
shouldBeFastSweep = ( radarStrength >= CONST_UPLINK_FAST_PING );
|
|
shouldBeDirectional = ( radarStrength >= CONST_DIRECTIONAL );
|
|
|
|
player.shouldBeEyesOn = shouldBeEyesOn;
|
|
player SetEyesOnUplinkEnabled( shouldBeEyesOn );
|
|
player.radarShowEnemyDirection = shouldBeDirectional;
|
|
player.radarMode = CONST_NORMAL_SWEEP;
|
|
player.hasRadar = shouldBeFullRadar;
|
|
player.isRadarBlocked = false;
|
|
|
|
if( shouldBeFastSweep )
|
|
{
|
|
player.radarMode = CONST_FAST_SWEEP;
|
|
}
|
|
}
|
|
|
|
//============================================
|
|
// tryUseUpLink
|
|
//============================================
|
|
tryUseUpLink( lifeId, streakName )
|
|
{
|
|
result = self maps\mp\killstreaks\_placeable::givePlaceable( streakName );
|
|
|
|
if( result )
|
|
{
|
|
// we want both to log to the same event?
|
|
self maps\mp\_matchdata::logKillstreakEvent( "uplink", self.origin );
|
|
}
|
|
|
|
// we're done carrying for sure and sometimes this might not get reset
|
|
// this fixes a bug where you could be carrying and have it in a place where it won't plant, get killed, now you can't scroll through killstreaks
|
|
self.isCarrying = undefined;
|
|
|
|
return result;
|
|
}
|
|
|
|
onCarried( streakName ) // self == obj
|
|
{
|
|
entNum = self GetEntityNumber();
|
|
if ( IsDefined( level.uplinks[ entNum ] ) )
|
|
{
|
|
self stopUplink();
|
|
}
|
|
}
|
|
|
|
onPlaced( streakName ) // self == obj
|
|
{
|
|
config = level.placeableConfigs[ streakName ];
|
|
|
|
self.owner notify( "uplink_deployed" );
|
|
|
|
self SetModel( config.modelBase );
|
|
|
|
self.immediateDeath = false;
|
|
self SetOtherEnt(self.owner);
|
|
self make_entity_sentient_mp( self.owner.team, true );
|
|
self.config = config;
|
|
|
|
self startUplink( true );
|
|
|
|
self thread watchEMPDamage();
|
|
|
|
// 2013-07-25 wallace: not sure if we need this still
|
|
/*
|
|
wait( 0.75 );
|
|
|
|
if( IsDefined(self) && (self touchingBadTrigger()) )
|
|
self notify( "death" );
|
|
*/
|
|
}
|
|
|
|
// Operations that need to be done when the uplink is first spawned
|
|
// AND when it resumes from
|
|
startUplink( playOpenAnim )
|
|
{
|
|
addUplinkToLevelList( self );
|
|
|
|
self thread playUplinkAnimations( playOpenAnim );
|
|
|
|
// play operation sound
|
|
self PlayLoopSound( self.config.activeSfx );
|
|
}
|
|
|
|
stopUplink()
|
|
{
|
|
self maps\mp\gametypes\_weapons::stopBlinkingLight();
|
|
|
|
self ScriptModelClearAnim();
|
|
|
|
if ( IsDefined( self.bombSquadModel ) )
|
|
{
|
|
self.bombSquadModel ScriptModelClearAnim();
|
|
}
|
|
|
|
removeUplinkFromLevelList( self );
|
|
|
|
self StopLoopSound();
|
|
}
|
|
|
|
#using_animtree( "animated_props" );
|
|
|
|
//============================================
|
|
// playUplinkAnimations
|
|
//============================================
|
|
playUplinkAnimations( playOpenAnim ) // self = uplink
|
|
{
|
|
self endon( "emp_damage" );
|
|
self endon( "death" );
|
|
self endon( "carried" );
|
|
|
|
if ( playOpenAnim )
|
|
{
|
|
waitTime = GetNotetrackTimes( %Satcom_killStreak, "stop anim" );
|
|
animLength = GetAnimLength( %Satcom_killStreak );
|
|
|
|
self ScriptModelPlayAnim( "Satcom_killStreak" );
|
|
if ( IsDefined( self.bombSquadModel ) )
|
|
{
|
|
self.bombSquadModel ScriptModelPlayAnim( "Satcom_killStreak" );
|
|
}
|
|
|
|
wait( waitTime[0] * animLength );
|
|
}
|
|
|
|
self ScriptModelPlayAnim( "Satcom_killStreak_idle" );
|
|
if ( IsDefined( self.bombSquadModel ) )
|
|
{
|
|
self.bombSquadModel ScriptModelPlayAnim( "Satcom_killStreak_idle" );
|
|
}
|
|
|
|
// play vfx
|
|
self thread maps\mp\gametypes\_weapons::doBlinkingLight( "tag_fx" );
|
|
}
|
|
|
|
onDestroyed( streakName, attacker, owner, sMeansOfDeath )
|
|
{
|
|
attacker notify( "destroyed_equipment" );
|
|
}
|
|
|
|
onDeath( streakName, attacker, owner, sMeansOfDeath )
|
|
{
|
|
self maps\mp\gametypes\_weapons::stopBlinkingLight();
|
|
|
|
self maps\mp\gametypes\_weapons::equipmentDeathVfx();
|
|
|
|
removeUplinkFromLevelList( self );
|
|
|
|
self ScriptModelClearAnim();
|
|
|
|
if(!self.immediateDeath)
|
|
{
|
|
wait( 3.0 );
|
|
}
|
|
|
|
self maps\mp\gametypes\_weapons::equipmentDeleteVfx();
|
|
}
|
|
|
|
//============================================
|
|
// addUplinkToLevelList
|
|
//============================================
|
|
addUplinkToLevelList( obj )
|
|
{
|
|
entNum = obj GetEntityNumber();
|
|
level.uplinks[entNum] = obj;
|
|
level notify( "update_uplink" );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// removeUplinkFromLevelList
|
|
//============================================
|
|
removeUplinkFromLevelList( obj )
|
|
{
|
|
entNum = obj GetEntityNumber();
|
|
level.uplinks[ entNum ] = undefined;
|
|
level notify( "update_uplink" );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// getRadarStrengthForTeam
|
|
//============================================
|
|
getRadarStrengthForTeam( team )
|
|
{
|
|
currentRadarStrength = 0;
|
|
|
|
foreach( satellite in level.uplinks )
|
|
{
|
|
if( IsDefined(satellite) && (satellite.team == team) )
|
|
currentRadarStrength++;
|
|
}
|
|
|
|
// give eyes-on when heli sniper is in the air
|
|
if ( currentRadarStrength == 0
|
|
&& IsDefined( level.heliSniperEyesOn )
|
|
&& level.heliSniperEyesOn.team == team
|
|
)
|
|
{
|
|
currentRadarStrength++;
|
|
}
|
|
|
|
return clamp( currentRadarStrength, CONST_UPLINK_MIN, CONST_UPLINK_MAX );
|
|
}
|
|
|
|
//============================================
|
|
// getRadarStrengthForPlayer
|
|
//============================================
|
|
getRadarStrengthForPlayer( player )
|
|
{
|
|
currentRadarStrength = 0;
|
|
|
|
foreach( satellite in level.uplinks )
|
|
{
|
|
if( IsDefined( satellite ) )
|
|
{
|
|
// not sure if it's safe to remove an item while we're iterating through it
|
|
if ( IsDefined( satellite.owner ) )
|
|
{
|
|
if ( satellite.owner.guid == player.guid)
|
|
currentRadarStrength++;
|
|
}
|
|
else
|
|
{
|
|
// if the owner has disconnected, stop tracking this satellite
|
|
entNum = satellite GetEntityNumber();
|
|
level.uplinks[ entNum ] = undefined;
|
|
}
|
|
}
|
|
}
|
|
|
|
// in FFA, eyes-on is useless, so automatically bump the benefit to tier 2
|
|
if ( !level.teamBased && currentRadarStrength > 0 )
|
|
currentRadarStrength++;
|
|
|
|
return clamp( currentRadarStrength, CONST_UPLINK_MIN, CONST_UPLINK_MAX );
|
|
}
|
|
|
|
|
|
//============================================
|
|
// getRadarStrengthForComExp
|
|
//============================================
|
|
getRadarStrengthForComExp( player )
|
|
{
|
|
currentRadarStrength = 0;
|
|
|
|
// Add to the radar strength regardless of which team places down the SAT COM
|
|
foreach( satellite in level.uplinks )
|
|
{
|
|
if( IsDefined(satellite) )
|
|
currentRadarStrength++;
|
|
}
|
|
|
|
// in FFA, eyes-on is useless, so automatically bump the benefit to tier 2
|
|
if ( !level.teamBased && currentRadarStrength > 0 )
|
|
currentRadarStrength++;
|
|
|
|
return clamp( currentRadarStrength, CONST_UPLINK_MIN, CONST_UPLINK_MAX );
|
|
}
|
|
|
|
uplink_override_moving_platform_death( data )
|
|
{
|
|
self.immediateDeath = true;
|
|
self notify( "death" );
|
|
}
|
|
|
|
watchEMPDamage()
|
|
{
|
|
// self endon( "carried" );
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
while( true )
|
|
{
|
|
// this handles any flash or concussion damage
|
|
self waittill( "emp_damage", attacker, duration );
|
|
|
|
self maps\mp\gametypes\_weapons::equipmentEmpStunVfx();
|
|
|
|
self stopUplink();
|
|
|
|
wait( duration );
|
|
|
|
self startUplink( false );
|
|
}
|
|
}
|
|
|
|
uplinkUpdateEyesOn()
|
|
{
|
|
level endon( "game_ended" );
|
|
|
|
while (true)
|
|
{
|
|
level waittill( "player_spawned", player );
|
|
|
|
eyesOn = ( IsDefined( player.shouldBeEyesOn ) && player.shouldBeEyesOn );
|
|
player SetEyesOnUplinkEnabled( eyesOn );
|
|
}
|
|
} |