boiii-scripts/mp/killstreaks/_killstreakrules.gsc
2023-04-13 17:30:38 +02:00

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 );
}
}
#/
}