boiii-scripts/shared/weapons/_scrambler.csc
2023-04-13 17:30:38 +02:00

401 lines
20 KiB
Plaintext

#using scripts\codescripts\struct;
#using scripts\shared\clientfield_shared;
#using scripts\shared\fx_shared;
#using scripts\shared\system_shared;
#using scripts\shared\util_shared;
#precache( "client_fx", "_t6/misc/fx_equip_light_red" );
#precache( "client_fx", "_t6/misc/fx_equip_light_green" );
#namespace scrambler;
function init_shared()
{
level._effect["scrambler_enemy_light"] = "_t6/misc/fx_equip_light_red";
level._effect["scrambler_friendly_light"] = "_t6/misc/fx_equip_light_green";
level.scramblerHandle = 1;
level.scramblerVOOuterRadius = 1200 * 1200;
level.scramblerInnerRadius = 500 * 500;
level.scramblesound = "mpl_scrambler_static";
level.globalscramblesound = "mpl_cuav_static";
level.scramblesoundalert = "mpl_scrambler_alert";
level.scramblesoundping = "mpl_scrambler_ping";
level.scramblesoundburst = "mpl_scrambler_burst";
clientfield::register( "missile", "scrambler", 1, 1, "int", &spawnedScrambler,!true, !true );
//TODO T7 - if this is going live again, the below 'counteruav' clientfield needs to get updated to be scrambler specific. In its current state it is shared with the counteruav
//clientfield::register( "scriptmover", "counteruav", VERSION_SHIP, 1, "int", &spawnedGlobalScramber,!CF_HOST_ONLY, !CF_CALLBACK_ZERO_ON_NEW_ENT );
level.scramblers = [];
level.playerPersistent = [];
localClientNum = 0;
util::waitforclient( localClientNum );
level thread scramblerUpdate( localClientNum );
level thread checkForPlayerSwitch();
}
function spawnedScrambler(localClientNum, set)
{
if ( !set )
return;
if ( localClientNum != 0 )
return;
self spawned(localClientNum, set, true);
}
function spawnedGlobalScramber( localClientNum, oldVal, newVal, bNewEnt, bInitialSnap, fieldName, bWasTimeJump )
{
if ( !newVal )
return;
if ( localClientNum != 0 )
return;
self spawned(localClientNum, newVal, false);
}
function spawned(localClientNum, set, isLocalized)
{
if ( !set )
return;
if ( localClientNum != 0 )
return;
scramblerHandle = level.scramblerHandle;
level.scramblerHandle++;
size = level.scramblers.size;
level.scramblers[size] = spawnstruct();
level.scramblers[size].scramblerHandle = scramblerHandle;
level.scramblers[size].cent = self;
level.scramblers[size].team = self.team;
level.scramblers[size].isLocalized = isLocalized;
level.scramblers[size].sndEnt = spawn( 0, self.origin, "script_origin" );
level.scramblers[size].sndId = -1;
level.scramblers[size].sndPingEnt = spawn( 0, self.origin, "script_origin" );
level.scramblers[size].sndPingId = -1;
players = level.localPlayers;
owner = self GetOwner( localClientNum );
util::local_players_entity_thread( self,&spawnedPerClient, isLocalized, scramblerHandle );
level thread cleanUpScramblerOnDelete( self, scramblerHandle, isLocalIzed, localClientNum );
}
function spawnedPerClient(localClientNum, isLocalized, scramblerHandle)
{
player = GetLocalPlayer( localClientNum );
isEnemy = self isEnemyScrambler( localClientNum );
owner = self GetOwner( localClientNum );
scramblerIndex = undefined;
for ( i = 0; i < level.scramblers.size; i++ )
{
if ( level.scramblers[i].scramblerHandle == scramblerHandle )
{
scramblerIndex = i;
break;
}
}
if ( !isdefined( scramblerIndex ) )
return;
if ( !isEnemy )
{
if ( isLocalized )
{
if ( owner == player && !IsSpectating( localClientNum, false ) )
{
player AddFriendlyScrambler( self.origin[0], self.origin[1], scramblerHandle );
}
//play ally sccramble sounds
if ( isdefined( level.scramblers[scramblerIndex].sndEnt ) )
{
level.scramblers[scramblerIndex].sndId = level.scramblers[scramblerIndex].sndEnt playloopsound(level.scramblesoundalert);
playsound (0, level.scramblesoundburst, level.scramblers[scramblerIndex].sndEnt.origin);
}
if ( isdefined( level.scramblers[scramblerIndex].sndPingEnt ) )
level.scramblers[scramblerIndex].sndPingId = level.scramblers[scramblerIndex].sndPingEnt playloopsound(level.scramblesoundping);
//iprintlnbold ("friendly Scrambler sound " + self.origin + level.scramblers[scramblerIndex].sndEnt.origin );
}
}
else
{
scrambleSound = level.scramblesound;
if ( isLocalized == false )
{
scrambleSound = level.globalscramblesound;
}
//play enemy sccramble sounds
if ( isdefined( level.scramblers[scramblerIndex].sndEnt ) )
level.scramblers[scramblerIndex].sndId = level.scramblers[scramblerIndex].sndEnt playloopsound(scrambleSound);
//iprintlnbold ("enemy Scrambler sound " + self.origin + level.scramblers[scramblerIndex].sndEnt.origin );
}
self thread fx::blinky_light( localClientNum, "tag_light", level._effect["scrambler_friendly_light"], level._effect["scrambler_enemy_light"] );
}
function scramblerUpdate( localClientNum )
{
nearestEnemy = level.scramblerVOOuterRadius;
nearestFriendly = level.scramblerVOOuterRadius;
for ( ;; )
{
// NOTE: this functionality is reliant on the level.localPlayers[] being valid. First check this if anything
// is reported as not working here.
players = level.localPlayers;
for (localClientNum = 0; localClientNum < players.size; localClientNum++)
{
player = players[localClientNum];
if (!isdefined ( player.team ))
continue; // hopefully it'll show up soon, so just do nothing for now
if (!isdefined ( level.playerPersistent[localClientNum] ) )
{
level.playerPersistent[localClientNum] = spawnStruct();
level.playerPersistent[localClientNum].previousTeam = player.team;
player removeallFriendlyScramblers();
}
if ( level.playerPersistent[localClientNum].previousTeam != player.team )
{
teamChanged = true;
level.playerPersistent[localClientNum].previousTeam = player.team;
}
else
teamChanged = false;
enemyScramblerAmount = 0.0;
friendlyScramblerAmount = 0.0;
nearestEnemy = level.scramblerVOOuterRadius;
nearestFriendly = level.scramblerVOOuterRadius;
isGlobalScrambler = 0;
distToScrambler = level.scramblerVOOuterRadius;
nearestEnemyScramblerCent = undefined;
for ( i = 0; i < level.scramblers.size; i++ )
{
if (!isdefined( level.scramblers[i].cent ) )
continue;
if ( isdefined( level.scramblers[i].cent.stunned ) && level.scramblers[i].cent.stunned )
{
level.scramblers[i].cent.reenable = true;
player RemoveFriendlyScrambler( level.scramblers[i].scramblerHandle );
continue;
}
else if ( isdefined( level.scramblers[i].cent.reenable ) && level.scramblers[i].cent.reenable )
{
teamChanged = true;
level.scramblers[i].cent.reenable = false;
}
if ( level.scramblers[i].isLocalized )
{
distToScrambler = distanceSquared( player.origin, level.scramblers[i].cent.origin );
}
if ( !level.scramblers[i].isLocalized && level.scramblers[i].cent isEnemyScrambler( localClientNum ) )
{
isGlobalScrambler = 1;
}
isEnemy = level.scramblers[i].cent isEnemyScrambler( localClientNum );
if ( level.scramblers[i].team != level.scramblers[i].cent.team )
{
scramblerTeamChanged = true;
level.scramblers[i].team = level.scramblers[i].cent.team;
}
else
{
scramblerTeamChanged = false;
}
if ( teamChanged || scramblerTeamChanged )
level.scramblers[i] restartSound( isEnemy );
if ( isEnemy )
{
if ( nearestEnemy > distToScrambler )
{
nearestEnemyScramblerCent = level.scramblers[i].cent;
nearestEnemy = distToScrambler;
}
if ( ( level.scramblers[i].isLocalized ) && ( teamChanged || scramblerTeamChanged ) )
player RemoveFriendlyScrambler( level.scramblers[i].scramblerHandle );
}
else if ( level.scramblers[i].isLocalized )
{
if ( nearestFriendly > distToScrambler )
nearestFriendly = distToScrambler;
owner = level.scramblers[i].cent GetOwner( localClientNum );
if ( owner == player && !IsSpectating( localClientNum, false ) )
{
if ( teamChanged || scramblerTeamChanged )
{
player AddFriendlyScrambler( level.scramblers[i].cent.origin[0], level.scramblers[i].cent.origin[1], level.scramblers[i].scramblerHandle );
}
}
}
}
if ( nearestEnemy < level.scramblerVOOuterRadius )
enemyVOScramblerAmount = 1 - ( ( nearestEnemy - level.scramblerInnerRadius ) / ( level.scramblerVOOuterRadius - level.scramblerInnerRadius ) );
else
enemyVOScramblerAmount = 0;
if ( nearestFriendly < level.scramblerInnerRadius )
friendlyScramblerAmount = 1.0;
else if ( nearestFriendly < level.scramblerVOOuterRadius )
friendlyScramblerAmount = 1 - ( ( nearestFriendly - level.scramblerInnerRadius ) / ( level.scramblerVOOuterRadius - level.scramblerInnerRadius ) );
player SetFriendlyScramblerAmount( friendlyScramblerAmount );
if ( level.scramblers.size > 0 && isdefined(nearestEnemyScramblerCent) )
{
player SetNearestEnemyScrambler( nearestEnemyScramblerCent );
}
else
{
player ClearNearestEnemyScrambler();
}
//player SetEnemyScramblerAmount( enemyScramblerAmount );
if ( isGlobalScrambler && ( player HasPerk( localClientNum, "specialty_immunecounteruav" ) == false ) )
player SetEnemyGlobalScrambler( 1 );
else
player SetEnemyGlobalScrambler( 0 );
if (enemyVOScramblerAmount > 1)
enemyVOScramblerAmount = 1;
if ( GetDvarfloat( "snd_futz" ) != enemyVOScramblerAmount )
SetDvar( "snd_futz", enemyVOScramblerAmount );
}
wait( 0.25 );
util::waitforallclients();
}
}
function cleanUpScramblerOnDelete( scramblerEnt, scramblerHandle, isLocalized, localClientNum )
{
scramblerEnt waittill( "entityshutdown" );
players = level.localPlayers;
for ( j = 0; j < level.scramblers.size; j++ )
{
size = level.scramblers.size;
if ( scramblerHandle == level.scramblers[j].scramblerHandle )
{
playsound (0, level.scramblesoundburst, level.scramblers[j].sndEnt.origin);
level.scramblers[j].sndEnt delete();
level.scramblers[j].sndEnt = self.scramblers[size - 1].sndEnt;
level.scramblers[j].sndPingEnt delete();
level.scramblers[j].sndPingEnt = self.scramblers[size - 1].sndPingEnt;
level.scramblers[j].cent = level.scramblers[size - 1].cent;
level.scramblers[j].scramblerHandle = level.scramblers[size - 1].scramblerHandle;
level.scramblers[j].team = level.scramblers[size - 1].team;
level.scramblers[j].isLocalized = level.scramblers[size - 1].isLocalized;
level.scramblers[size - 1] = undefined;
break;
}
}
if ( isLocalized )
{
for ( i = 0; i < players.size; i++ )
{
players[i] RemoveFriendlyScrambler( scramblerHandle );
}
}
}
function isEnemyScrambler( localClientNum )
{
/#
if ( GetDvarInt( "scr_forceEnemyScrambler", 0 ) )
return true;
#/
enemy = !util::friend_not_foe(localClientNum);
return enemy;
}
function checkForPlayerSwitch()
{
while ( true )
{
level waittill( "player_switch" );
waittillframeend;
players = level.localPlayers;
for (localClientNum = 0; localClientNum < players.size; localClientNum++)
{
for ( j = 0; j < level.scramblers.size; j++ )
{
ent = level.scramblers[j].cent;
ent thread fx::stop_blinky_light( localClientNum );
ent thread fx::blinky_light( localClientNum, "tag_light", level._effect["scrambler_friendly_light"], level._effect["scrambler_enemy_light"] );
isEnemy = ent isEnemyScrambler( localClientNum );
level.scramblers[j] restartSound( isEnemy );
}
}
}
}
function restartSound( isEnemy )
{
if ( self.sndId != -1 )
{
self.sndEnt StopAllLoopSounds( 0.1 );
self.sndId = -1;
}
if ( !isEnemy )
{
if ( self.isLocalized )
{
self.sndId = self.sndEnt playloopsound( level.scramblesoundalert );
}
}
else
{
isLocalized = self.isLocalized;
scrambleSound = level.scramblesound;
if ( isLocalized == false )
{
scrambleSound = level.globalscramblesound;
}
self.sndId = self.sndEnt playloopsound( scrambleSound );
}
}