488 lines
26 KiB
Plaintext
488 lines
26 KiB
Plaintext
#using scripts\codescripts\struct;
|
|
|
|
#using scripts\shared\popups_shared;
|
|
#using scripts\shared\util_shared;
|
|
|
|
|
|
|
|
|
|
#using scripts\mp\_util;
|
|
#using scripts\mp\killstreaks\_killstreaks;
|
|
#using scripts\mp\killstreaks\_emp;
|
|
#using scripts\mp\gametypes\_globallogic_audio;
|
|
|
|
#namespace killstreakrules;
|
|
|
|
function init()
|
|
{
|
|
level.killstreakrules = [];
|
|
level.killstreaktype = [];
|
|
level.killstreaks_triggered = [];
|
|
level.matchRecorderKillstreakKills = [];
|
|
|
|
if( !isdefined( level.globalKillstreaksCalled ) )
|
|
{
|
|
level.globalKillstreaksCalled = 0;
|
|
}
|
|
|
|
// Rule name, max count per team count
|
|
createRule( "ai_tank", 4, 2);
|
|
createRule( "airsupport", 1, 1);
|
|
createRule( "combatrobot", 4, 2);
|
|
createRule( "chopper", 2, 1);
|
|
createRule( "chopperInTheAir", 2, 1);
|
|
createRule( "counteruav", 6, 3);
|
|
createRule( "dart", 4, 2);
|
|
createRule( "dogs", 1, 1);
|
|
createRule( "drone_strike", 1, 1);
|
|
createRule( "emp", 2, 1);
|
|
createRule( "firesupport", 1, 1);
|
|
createRule( "missiledrone", 3, 3);
|
|
createRule( "missileswarm", 1, 1);
|
|
createRule( "planemortar", 1, 1);
|
|
createRule( "playercontrolledchopper", 1, 1);
|
|
createRule( "qrdrone", 3, 2);
|
|
createRule( "uav", 10, 5);
|
|
createRule( "raps" , 2, 1);
|
|
createRule( "rcxd", 4, 2);
|
|
createRule( "remote_missile", 2, 1);
|
|
createRule( "remotemortar", 1, 1);
|
|
createRule( "satellite", 2, 1);
|
|
createRule( "sentinel", 4, 2);
|
|
createRule( "straferun", 1, 1);
|
|
createRule( "supplydrop", 4, 4);
|
|
createRule( "targetableent", 32, 32);
|
|
createRule( "turret", 8, 4);
|
|
createRule( "vehicle", 7, 7);
|
|
createRule( "weapon", 12, 6);
|
|
|
|
// KILLSTREAK Rule Name adds checks
|
|
addKillstreakToRule( "ai_tank_drop", "ai_tank", true, true );
|
|
addKillstreakToRule( "airstrike", "airsupport", true, true );
|
|
addKillstreakToRule( "airstrike", "vehicle", true, true );
|
|
addKillstreakToRule( "artillery", "firesupport", true, true );
|
|
addKillstreakToRule( "auto_tow", "turret", true, true );
|
|
addKillstreakToRule( "autoturret", "turret", true, true );
|
|
addKillstreakToRule( "combat_robot", "combatrobot", true, true );
|
|
addKillstreakToRule( "counteruav", "counteruav", true, true );
|
|
addKillstreakToRule( "counteruav", "targetableent", true, true );
|
|
addKillstreakToRule( "dart", "dart", true, true );
|
|
addKillstreakToRule( "dogs", "dogs", true, true );
|
|
addKillstreakToRule( "dogs_lvl2", "dogs", true, true );
|
|
addKillstreakToRule( "dogs_lvl3", "dogs", true, true );
|
|
addKillstreakToRule( "drone_strike", "drone_strike", true, true );
|
|
addKillstreakToRule( "emp", "emp", true, true );
|
|
addKillstreakToRule( "helicopter", "chopper", true, true );
|
|
addKillstreakToRule( "helicopter", "chopperInTheAir", true, false );
|
|
addKillstreakToRule( "helicopter", "playercontrolledchopper", false, true );
|
|
addKillstreakToRule( "helicopter", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter", "vehicle", true, true );
|
|
|
|
addKillstreakToRule( "helicopter_comlink", "chopper", true, true );
|
|
addKillstreakToRule( "helicopter_comlink", "chopperInTheAir", true, false );
|
|
addKillstreakToRule( "helicopter_comlink", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_comlink", "vehicle", true, true );
|
|
|
|
addKillstreakToRule( "helicopter_guard", "airsupport", true, true );
|
|
|
|
addKillstreakToRule( "helicopter_gunner", "chopperInTheAir", true, false );
|
|
addKillstreakToRule( "helicopter_gunner", "playercontrolledchopper", true, true );
|
|
addKillstreakToRule( "helicopter_gunner", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_gunner", "vehicle", true, true );
|
|
|
|
addKillstreakToRule( "helicopter_gunner_assistant", "chopperInTheAir", true, false );
|
|
addKillstreakToRule( "helicopter_gunner_assistant", "playercontrolledchopper", true, true );
|
|
addKillstreakToRule( "helicopter_gunner_assistant", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_gunner_assistant", "vehicle", true, true );
|
|
|
|
addKillstreakToRule( "helicopter_player_firstperson", "vehicle", true, true );
|
|
addKillstreakToRule( "helicopter_player_firstperson", "chopperInTheAir", true, true );
|
|
addKillstreakToRule( "helicopter_player_firstperson", "playercontrolledchopper", true, true );
|
|
addKillstreakToRule( "helicopter_player_firstperson", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_player_gunner", "chopperInTheAir", true, true );
|
|
addKillstreakToRule( "helicopter_player_gunner", "playercontrolledchopper", true, true );
|
|
addKillstreakToRule( "helicopter_player_gunner", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_player_gunner", "vehicle", true, true );
|
|
addKillstreakToRule( "helicopter_x2", "chopper", true, true );
|
|
addKillstreakToRule( "helicopter_x2", "chopperInTheAir", true, false );
|
|
addKillstreakToRule( "helicopter_x2", "playercontrolledchopper", false, true );
|
|
addKillstreakToRule( "helicopter_x2", "targetableent", true, true );
|
|
addKillstreakToRule( "helicopter_x2", "vehicle", true, true );
|
|
addKillstreakToRule( "m202_flash", "weapon", true, true );
|
|
addKillstreakToRule( "m220_tow", "weapon", true, true );
|
|
addKillstreakToRule( "m220_tow_drop", "supplydrop", true, true );
|
|
addKillstreakToRule( "m220_tow_drop", "vehicle", true, true );
|
|
addKillstreakToRule( "m220_tow_killstreak", "weapon", true, true );
|
|
addKillstreakToRule( "m32", "weapon", true, true );
|
|
addKillstreakToRule( "m32_drop", "weapon", true, true );
|
|
addKillstreakToRule( "microwave_turret", "turret", true, true );
|
|
addKillstreakToRule( "minigun", "weapon", true, true );
|
|
addKillstreakToRule( "minigun_drop", "weapon", true, true );
|
|
addKillstreakToRule( "missile_drone", "missiledrone", true, true );
|
|
addKillstreakToRule( "missile_swarm", "missileswarm", true, true );
|
|
addKillstreakToRule( "mortar", "firesupport", true, true );
|
|
addKillstreakToRule( "mp40_drop", "weapon", true, true );
|
|
addKillstreakToRule( "napalm", "airsupport", true, true );
|
|
addKillstreakToRule( "napalm", "vehicle", true, true );
|
|
addKillstreakToRule( "planemortar", "planemortar", true, true );
|
|
addKillstreakToRule( "qrdrone", "qrdrone", true, true );
|
|
addKillstreakToRule( "qrdrone", "vehicle", true, true );
|
|
addKillstreakToRule( "uav", "uav", true, true );
|
|
addKillstreakToRule( "uav", "targetableent", true, true );
|
|
addKillstreakToRule( "satellite", "satellite", true, true );
|
|
addKillstreakToRule( "raps", "raps", true, true );
|
|
addKillstreakToRule( "rcbomb", "rcxd", true, true );
|
|
addKillstreakToRule( "remote_missile", "targetableent", true, true );
|
|
addKillstreakToRule( "remote_missile", "remote_missile", true, true );
|
|
addKillstreakToRule( "remote_mortar", "remotemortar", true, true );
|
|
addKillstreakToRule( "remote_mortar", "targetableent", true, true );
|
|
addKillstreakToRule( "sentinel", "sentinel", true, true );
|
|
addKillstreakToRule( "straferun", "straferun", true, true );
|
|
addKillstreakToRule( "supply_drop", "supplydrop", true, true );
|
|
addKillstreakToRule( "supply_drop", "targetableent", true, true );
|
|
addKillstreakToRule( "supply_drop", "vehicle", true, true );
|
|
addKillstreakToRule( "supply_station", "supplydrop", true, true );
|
|
addKillstreakToRule( "supply_station", "targetableent", true, true );
|
|
addKillstreakToRule( "supply_station", "vehicle", true, true );
|
|
addKillstreakToRule( "tow_turret_drop", "supplydrop", true, true );
|
|
addKillstreakToRule( "tow_turret_drop", "vehicle", true, true );
|
|
addKillstreakToRule( "turret_drop", "supplydrop", true, true );
|
|
addKillstreakToRule( "turret_drop", "vehicle", true, true );
|
|
}
|
|
|
|
function createRule( rule, maxAllowable, maxAllowablePerTeam )
|
|
{
|
|
level.killstreakrules[rule] = spawnstruct();
|
|
level.killstreakrules[rule].cur = 0;
|
|
level.killstreakrules[rule].curTeam = [];
|
|
level.killstreakrules[rule].max = maxAllowable;
|
|
level.killstreakrules[rule].maxPerTeam = maxAllowablePerTeam;
|
|
}
|
|
|
|
function addKillstreakToRule( killstreak, rule, countTowards, checkAgainst, inventoryVariant )
|
|
{
|
|
if ( !isdefined (level.killstreaktype[killstreak] ) )
|
|
level.killstreaktype[killstreak] = [];
|
|
|
|
keys = GetArrayKeys( level.killstreaktype[killstreak] );
|
|
|
|
// you need to add a rule before adding it to a killstreak
|
|
assert( isdefined(level.killstreakrules[rule] ) );
|
|
|
|
if ( !isdefined( level.killstreaktype[killstreak][rule] ) )
|
|
level.killstreaktype[killstreak][rule] = spawnstruct();
|
|
|
|
level.killstreaktype[killstreak][rule].counts = countTowards;
|
|
|
|
level.killstreaktype[killstreak][rule].checks = checkAgainst;
|
|
|
|
if( !( isdefined( inventoryVariant ) && inventoryVariant ) )
|
|
addKillstreakToRule( "inventory_" + killstreak, rule, countTowards, checkAgainst, true );
|
|
}
|
|
|
|
// returns killstreakid or if killstreak is not allowed
|
|
function killstreakStart( hardpointType, team, hacked, displayTeamMessage )
|
|
{
|
|
/#
|
|
assert( isdefined( team ), "team needs to be defined" );
|
|
#/
|
|
|
|
if ( self isKillstreakAllowed( hardpointType, team ) == false )
|
|
return (-1);
|
|
|
|
assert ( isdefined ( hardpointType ) );
|
|
|
|
if( !isdefined( hacked ) )
|
|
hacked = false;
|
|
|
|
if ( !isdefined( displayTeamMessage ) )
|
|
displayTeamMessage = true;
|
|
|
|
if( GetDvarInt( "teamOpsEnabled" ) == 1 )
|
|
displayTeamMessage = false;
|
|
|
|
if ( displayTeamMessage == true )
|
|
{
|
|
if ( !hacked )
|
|
self displayKillstreakStartTeamMessageToAll( hardpointType );
|
|
}
|
|
|
|
keys = GetArrayKeys( level.killstreaktype[hardpointType] );
|
|
|
|
foreach( key in keys )
|
|
{
|
|
// Check if killstreak is counted by this rule
|
|
if ( !level.killstreaktype[hardpointType][key].counts )
|
|
continue;
|
|
|
|
assert( isdefined(level.killstreakrules[key] ) );
|
|
level.killstreakrules[key].cur++;
|
|
if ( level.teambased )
|
|
{
|
|
if ( !isdefined( level.killstreakrules[key].curTeam[team] ) )
|
|
level.killstreakrules[key].curTeam[team] = 0;
|
|
level.killstreakrules[key].curTeam[team]++;
|
|
}
|
|
}
|
|
|
|
level notify( "killstreak_started", hardpointType, team, self );
|
|
|
|
killstreak_id = level.globalKillstreaksCalled;
|
|
level.globalKillstreaksCalled++;
|
|
|
|
killstreak_data = [];
|
|
killstreak_data[ "caller" ] = self GetXUID();
|
|
killstreak_data[ "spawnid" ] = getplayerspawnid( self );
|
|
killstreak_data[ "starttime" ] = gettime();
|
|
killstreak_data[ "type" ] = hardpointType;
|
|
killstreak_data[ "endtime" ] = 0;
|
|
level.matchRecorderKillstreakKills[ killstreak_id ] = 0;
|
|
|
|
level.killstreaks_triggered[ killstreak_id ] = killstreak_data;
|
|
|
|
/#
|
|
killstreak_debug_text( "Started killstreak: " + hardpointtype + " for team: " + team + " id: " + killstreak_id );
|
|
#/
|
|
|
|
return killstreak_id;
|
|
}
|
|
|
|
function displayKillstreakStartTeamMessageToAll( hardpointType )
|
|
{
|
|
if( GetDvarInt( "teamOpsEnabled" ) == 1 )
|
|
return;
|
|
|
|
if ( isdefined( level.killstreaks[hardpointType] ) && isdefined( level.killstreaks[hardpointType].inboundtext ) )
|
|
level thread popups::DisplayKillstreakTeamMessageToAll( hardpointType, self );
|
|
}
|
|
|
|
function RecordKillstreakEndDirect(eventIndex, recordStreakIndex, totalKills)
|
|
{
|
|
player = self;
|
|
|
|
player RecordKillstreakEndEvent( eventIndex, recordStreakIndex, totalKills );
|
|
|
|
player.killstreakEvents[recordStreakIndex] = undefined;
|
|
}
|
|
|
|
function RecordKillstreakEnd(recordStreakIndex, totalKills)
|
|
{
|
|
player = self;
|
|
|
|
if(!IsPlayer(player))
|
|
return;
|
|
|
|
if(!IsDefined(totalKills))
|
|
totalkills = 0;
|
|
|
|
if(!isDefined(player.killstreakEvents))
|
|
{
|
|
// This may store an eventIndex or number of kills, depending on whether a killstreak event or an end event happens first, respectively
|
|
player.killstreakEvents = associativeArray();
|
|
}
|
|
eventIndex = player.killstreakEvents[recordStreakIndex];
|
|
// Note that some killstreaks fire their end before their begin, so we need to check if the eventIndex is defined to determine that
|
|
// Two cases - 1) KillstreakEvent happens first (correctly)
|
|
if(isDefined(eventIndex))
|
|
{
|
|
player RecordKillstreakEndDirect(eventIndex, recordStreakIndex, totalKills);
|
|
}
|
|
else
|
|
{
|
|
// KillstreakEndEvent happens first
|
|
player.killstreakEvents[recordStreakIndex] = totalKills;
|
|
}
|
|
}
|
|
|
|
function killstreakStop( hardpointType, team, id )
|
|
{
|
|
/#
|
|
assert( isdefined( team ), "team needs to be defined" );
|
|
#/
|
|
|
|
assert ( isdefined ( hardpointType ) );
|
|
//assert( isdefined( id ), "Must provide the associated killstreak_id for " + hardpointType );
|
|
|
|
/#
|
|
idstr = "undefined";
|
|
if (IsDefined(id))
|
|
idstr = id;
|
|
killstreak_debug_text( "Stopped killstreak: " + hardpointtype + " for team: " + team + " id: " + idstr );
|
|
#/
|
|
keys = GetArrayKeys( level.killstreaktype[hardpointType] );
|
|
|
|
foreach( key in keys )
|
|
{
|
|
// Check if killstreak is counted by this rule
|
|
if ( !level.killstreaktype[hardpointType][key].counts )
|
|
continue;
|
|
|
|
assert( isdefined(level.killstreakrules[key] ) );
|
|
level.killstreakrules[key].cur--;
|
|
|
|
assert (level.killstreakrules[key].cur >= 0 );
|
|
|
|
if ( level.teambased )
|
|
{
|
|
assert( isdefined( team ) );
|
|
assert( isdefined( level.killstreakrules[key].curTeam[team] ) );
|
|
|
|
level.killstreakrules[key].curTeam[team]--;
|
|
assert (level.killstreakrules[key].curTeam[team] >= 0 );
|
|
}
|
|
}
|
|
|
|
if ( !isdefined(id) || (id == (-1)) )
|
|
{
|
|
killstreak_debug_text("WARNING! Invalid killstreak id detected for " + hardpointType );
|
|
|
|
// log a lightweight entry in the DB to assist tracking down invalid cases
|
|
bbPrint( "mpkillstreakuses", "starttime %d endtime %d name %s team %s", 0, GetTime(), hardpointType, team );
|
|
return;
|
|
}
|
|
level.killstreaks_triggered[ id ][ "endtime" ] = GetTime();
|
|
|
|
totalKillsWithThisKillstreak = level.matchRecorderKillstreakKills[ id ];
|
|
|
|
bbPrint( "mpkillstreakuses", "starttime %d endtime %d spawnid %d name %s team %s",
|
|
level.killstreaks_triggered[ id ][ "starttime" ],
|
|
level.killstreaks_triggered[ id ][ "endtime" ],
|
|
level.killstreaks_triggered[ id ][ "spawnid" ],
|
|
hardpointType,
|
|
team );
|
|
|
|
level.killstreaks_triggered[ id ] = undefined;
|
|
level.matchRecorderKillstreakKills[ id ] = undefined;
|
|
|
|
if( isdefined( level.killstreaks[hardpointType].menuname ) )
|
|
{
|
|
recordStreakIndex = level.killstreakindices[level.killstreaks[hardpointType].menuname];
|
|
if ( isdefined( self ) && isdefined( recordStreakIndex ) && ( !isdefined( self.activatingKillstreak ) || !self.activatingKillstreak ) )
|
|
{
|
|
entity = self;
|
|
if(isDefined(entity.owner) )
|
|
{
|
|
entity = entity.owner;
|
|
}
|
|
|
|
entity RecordKillstreakEnd(recordstreakindex, totalkillswiththiskillstreak);
|
|
}
|
|
}
|
|
}
|
|
|
|
function isKillstreakAllowed( hardpointType, team )
|
|
{
|
|
/#
|
|
assert( isdefined( team ), "team needs to be defined" );
|
|
#/
|
|
|
|
assert ( isdefined ( hardpointType ) );
|
|
|
|
// general failsafe for all scorestreaks
|
|
if ( self killstreaks::is_killstreak_start_blocked() )
|
|
return false;
|
|
|
|
isAllowed = true;
|
|
|
|
keys = GetArrayKeys( level.killstreaktype[hardpointType] );
|
|
|
|
foreach( key in keys )
|
|
{
|
|
// Check if killstreak is restricted by this rule
|
|
if ( !level.killstreaktype[hardpointType][key].checks )
|
|
continue;
|
|
|
|
if ( level.killstreakrules[key].max != 0 )
|
|
{
|
|
if (level.killstreakrules[key].cur >= level.killstreakrules[key].max)
|
|
{
|
|
/#
|
|
killstreak_debug_text( "Exceeded " + key + " overall" );
|
|
#/
|
|
isAllowed = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( level.teambased && level.killstreakrules[key].maxPerTeam != 0 )
|
|
{
|
|
if ( !isdefined( level.killstreakrules[key].curTeam[team] ) )
|
|
level.killstreakrules[key].curTeam[team] = 0;
|
|
|
|
if (level.killstreakrules[key].curTeam[team] >= level.killstreakrules[key].maxPerTeam)
|
|
{
|
|
isAllowed = false;
|
|
/#
|
|
killstreak_debug_text( "Exceeded " + key + " team" );
|
|
#/
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if ( isdefined( self.lastStand ) && self.lastStand )
|
|
{
|
|
/#
|
|
killstreak_debug_text( "In LastStand" );
|
|
#/
|
|
isAllowed = false;
|
|
}
|
|
|
|
isEMPed = false;
|
|
// should only be needed in case of a hacked client, the client checks the EMP flag prior to switching to the killstreak weapon
|
|
if ( self IsEMPJammed() )
|
|
{
|
|
/#
|
|
killstreak_debug_text( "EMP active" );
|
|
#/
|
|
isAllowed = false;
|
|
isEMPed = true;
|
|
if ( self EMP::EnemyEMPActive() )
|
|
{
|
|
if ( isdefined( level.empEndTime ) )
|
|
{
|
|
secondsLeft = int( ( level.empendtime - getTime() ) / 1000 );
|
|
if ( secondsLeft > 0 )
|
|
{
|
|
self iprintlnbold( &"KILLSTREAK_NOT_AVAILABLE_EMP_ACTIVE", secondsLeft );
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( isAllowed == false )
|
|
{
|
|
if ( isdefined( level.killstreaks[hardpointType] ) && isdefined( level.killstreaks[hardpointType].notAvailableText ) )
|
|
{
|
|
self iprintlnbold( level.killstreaks[hardpointType].notAvailableText );
|
|
|
|
if ( !isdefined( self.currentKillstreakDialog ) && level.killstreaks[hardpointType].utilizesAirspace && isEMPed == false )
|
|
{
|
|
self globallogic_audio::play_taacom_dialog( "airspaceFull" );
|
|
}
|
|
}
|
|
}
|
|
|
|
return isAllowed;
|
|
}
|
|
|
|
function killstreak_debug_text( text )
|
|
{
|
|
/#
|
|
level.killstreak_rule_debug = GetDvarInt( "scr_killstreak_rule_debug", 0 ); // debug mode, draws debugging info on screen
|
|
|
|
if ( isdefined( level.killstreak_rule_debug ) )
|
|
{
|
|
if ( level.killstreak_rule_debug == 1.0 )
|
|
{
|
|
iprintln( "KSR: " + text + "\n" );
|
|
}
|
|
else if ( level.killstreak_rule_debug == 2.0 )
|
|
{
|
|
iprintlnbold( "KSR: " + text );
|
|
}
|
|
}
|
|
#/
|
|
} |