1955 lines
71 KiB
Plaintext
1955 lines
71 KiB
Plaintext
#include maps\mp\_utility;
|
|
#include common_scripts\utility;
|
|
#include maps\mp\gametypes\_hud_util;
|
|
|
|
CRATE_KILLCAM_OFFSET = ( 0, 0, -200);
|
|
GRAVITY_UNITS_PER_SECOND = 800;
|
|
CRATE_ICON_Z_OFFSET = 60;
|
|
|
|
init()
|
|
{
|
|
if ( GetDvarInt( "virtuallobbyactive", 0 ) )
|
|
return;
|
|
|
|
level._effect[ "airdrop_crate_destroy" ] = loadfx( "vfx/explosion/vehicle_pdrone_explosion" );
|
|
level._effect[ "airdrop_crate_trap_explode" ] = LoadFX( "vfx/explosion/frag_grenade_default" );
|
|
|
|
setAirDropCrateCollision( "airdrop_crate" ); // old care package entities
|
|
setAirDropCrateCollision( "care_package" ); // new care package entities
|
|
assert( IsDefined(level.airDropCrateCollision) );
|
|
|
|
level.numDropCrates = 0;
|
|
level.crateTypes = [];
|
|
|
|
level.killstreakWieldWeapons["airdrop_trap_explosive_mp"] = "airdrop_assault";
|
|
|
|
level.killStreakFuncs["airdrop_reinforcement_common"] = ::tryUseReinforcementCommon;
|
|
level.killStreakFuncs["airdrop_reinforcement_uncommon"] = ::tryUseReinforcementUncommon;
|
|
level.killStreakFuncs["airdrop_reinforcement_rare"] = ::tryUseReinforcementRare;
|
|
level.killStreakFuncs["airdrop_reinforcement_practice"] = ::tryUseReinforcementPractice;
|
|
|
|
addCrateTypes_standard();
|
|
|
|
level.secondaryReinforcementHintText = [];
|
|
level.secondaryReinforcementHintText[ "specialty_extended_battery" ] = &"PERKS_EXO_BATTERY";
|
|
level.secondaryReinforcementHintText[ "specialty_class_lowprofile" ] = &"PERKS_LOWPROFILE";
|
|
level.secondaryReinforcementHintText[ "specialty_class_flakjacket" ] = &"PERKS_FLAKJACKET";
|
|
level.secondaryReinforcementHintText[ "specialty_class_lightweight" ] = &"PERKS_LIGHTWEIGHT";
|
|
level.secondaryReinforcementHintText[ "specialty_class_blindeye" ] = &"PERKS_BLINDEYE";
|
|
level.secondaryReinforcementHintText[ "specialty_class_coldblooded" ] = &"PERKS_COLDBLOODED";
|
|
level.secondaryReinforcementHintText[ "specialty_class_peripherals" ] = &"PERKS_PERIPHERALS";
|
|
level.secondaryReinforcementHintText[ "specialty_class_fasthands" ] = &"PERKS_FASTHANDS";
|
|
level.secondaryReinforcementHintText[ "specialty_class_dexterity" ] = &"PERKS_DEXTERITY";
|
|
level.secondaryReinforcementHintText[ "specialty_exo_blastsuppressor" ] = &"PERKS_EXO_BLASTSUPPRESSOR";
|
|
level.secondaryReinforcementHintText[ "specialty_class_hardwired" ] = &"PERKS_HARDWIRED";
|
|
level.secondaryReinforcementHintText[ "specialty_class_toughness" ] = &"PERKS_TOUGHNESS";
|
|
level.secondaryReinforcementHintText[ "specialty_class_scavenger" ] = &"PERKS_SCAVENGER";
|
|
level.secondaryReinforcementHintText[ "specialty_class_hardline" ] = &"PERKS_HARDLINE";
|
|
|
|
if( IsDefined(level.customCrateFunc) )
|
|
[[level.customCrateFunc]]();
|
|
|
|
generateMaxWeightedCrateValue();
|
|
|
|
/#
|
|
SetDevDvarIfUninitialized( "scr_crateOverride", "" );
|
|
SetDevDvarIfUninitialized( "scr_crateTypeOverride", "" );
|
|
#/
|
|
|
|
level.mapKillstreakAutoDropIndex = RandomInt( 4 );
|
|
}
|
|
|
|
addCrateTypes_standard()
|
|
{
|
|
mapStreak = level.mapKillStreak;
|
|
if ( IsDefined( level.mapStreaksDisabled ) && level.mapStreaksDisabled )
|
|
mapStreak = undefined;
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_assault", mapStreak, 168, ::killstreakCrateThink, level.mapKillstreakPickupString, mapStreak );
|
|
addCrateType( "airdrop_assault", "b", 168, ::killstreakCrateThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_heavy_resistance" );
|
|
addCrateType( "airdrop_assault", "c", 168, ::killstreakCrateThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_rippable", "sentry_rocket_turret" );
|
|
addCrateType( "airdrop_assault", "d", 168, ::killstreakCrateThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_assault", "e", 168, ::killstreakCrateThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_chem", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_assault", "f", 168, ::killstreakCrateThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_cloak", "recon_ugv_assist_points" );
|
|
addCrateType( "airdrop_assault", "g", 168, ::killstreakCrateThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_paint_grenade", "recon_ugv_assist_points" );
|
|
addCrateType( "airdrop_assault", "h", 98, ::killstreakCrateThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_beam" );
|
|
addCrateType( "airdrop_assault", "i", 98, ::killstreakCrateThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_width", "orbital_strike_laser_duration" );
|
|
addCrateType( "airdrop_assault", "j", 100, ::killstreakCrateThink, &"MP_UAV_PICKUP", "uav", "uav_enemy_direction", "uav_orbit" );
|
|
addCrateType( "airdrop_assault", "k", 100, ::killstreakCrateThink, &"MP_UAV_PICKUP", "uav", "uav_scrambler", "uav_increased_time", "uav_paint_outline" );
|
|
addCrateType( "airdrop_assault", "l", 40, ::killstreakCrateThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_rockets", "warbird_coop_offensive" );
|
|
addCrateType( "airdrop_assault", "m", 40, ::killstreakCrateThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_ai_attack", "warbird_flares", "warbird_time" );
|
|
addCrateType( "airdrop_assault", "n", 30, ::killstreakCrateThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_mg", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_assault", "o", 30, ::killstreakCrateThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_ai", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_assault", "p", 20, ::killstreakCrateThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_turret", "orbitalsupport_coop_offensive","orbitalsupport_ammo" );
|
|
addCrateType( "airdrop_assault", "q", 20, ::killstreakCrateThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_rockets", "orbitalsupport_flares", "orbitalsupport_time" );
|
|
addCrateType( "airdrop_assault", "r", 20, ::killstreakCrateThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_two", "strafing_run_airstrike_flares" );
|
|
addCrateType( "airdrop_assault", "s", 20, ::killstreakCrateThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_stealth" );
|
|
addCrateType( "airdrop_assault", "t", 10, ::killstreakCrateThink, &"MP_EMP_PICKUP", "emp", "emp_assist", "emp_flash" );
|
|
addCrateType( "airdrop_assault", "u", 10, ::killstreakCrateThink, &"MP_EMP_PICKUP", "emp", "emp_streak_kill", "emp_equipment_kill", "emp_time_1" );
|
|
addCrateType( "airdrop_assault", "v", 10, ::killstreakCrateThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_radar", "heavy_exosuit_punch" );
|
|
addCrateType( "airdrop_assault", "w", 10, ::killstreakCrateThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_trophy", "heavy_exosuit_rockets", "heavy_exosuit_eject" );
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_assault_odds", mapStreak, 136, ::killstreakCrateThink, level.mapKillstreakPickupString, mapStreak );
|
|
addCrateType( "airdrop_assault_odds", "b", 136, ::killstreakCrateThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_heavy_resistance" );
|
|
addCrateType( "airdrop_assault_odds", "c", 136, ::killstreakCrateThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_rippable", "sentry_rocket_turret" );
|
|
addCrateType( "airdrop_assault_odds", "d", 136, ::killstreakCrateThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_assault_odds", "e", 136, ::killstreakCrateThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_chem", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_assault_odds", "f", 136, ::killstreakCrateThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_cloak", "recon_ugv_assist_points" );
|
|
addCrateType( "airdrop_assault_odds", "g", 136, ::killstreakCrateThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_paint_grenade", "recon_ugv_assist_points" );
|
|
addCrateType( "airdrop_assault_odds", "h", 116, ::killstreakCrateThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_beam" );
|
|
addCrateType( "airdrop_assault_odds", "i", 116, ::killstreakCrateThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_width", "orbital_strike_laser_duration" );
|
|
addCrateType( "airdrop_assault_odds", "j", 100, ::killstreakCrateThink, &"MP_UAV_PICKUP", "uav", "uav_enemy_direction", "uav_orbit" );
|
|
addCrateType( "airdrop_assault_odds", "k", 100, ::killstreakCrateThink, &"MP_UAV_PICKUP", "uav", "uav_scrambler", "uav_increased_time", "uav_paint_outline" );
|
|
addCrateType( "airdrop_assault_odds", "l", 60, ::killstreakCrateThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_rockets", "warbird_coop_offensive" );
|
|
addCrateType( "airdrop_assault_odds", "m", 60, ::killstreakCrateThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_ai_attack", "warbird_flares", "warbird_time" );
|
|
addCrateType( "airdrop_assault_odds", "n", 50, ::killstreakCrateThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_mg", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_assault_odds", "o", 50, ::killstreakCrateThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_ai", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_assault_odds", "p", 40, ::killstreakCrateThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_turret", "orbitalsupport_coop_offensive","orbitalsupport_ammo" );
|
|
addCrateType( "airdrop_assault_odds", "q", 40, ::killstreakCrateThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_rockets", "orbitalsupport_flares", "orbitalsupport_time" );
|
|
addCrateType( "airdrop_assault_odds", "r", 40, ::killstreakCrateThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_two", "strafing_run_airstrike_flares" );
|
|
addCrateType( "airdrop_assault_odds", "s", 40, ::killstreakCrateThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_stealth" );
|
|
addCrateType( "airdrop_assault_odds", "t", 30, ::killstreakCrateThink, &"MP_EMP_PICKUP", "emp", "emp_assist", "emp_flash" );
|
|
addCrateType( "airdrop_assault_odds", "u", 30, ::killstreakCrateThink, &"MP_EMP_PICKUP", "emp", "emp_streak_kill", "emp_equipment_kill", "emp_time_1" );
|
|
addCrateType( "airdrop_assault_odds", "v", 30, ::killstreakCrateThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_radar", "heavy_exosuit_punch" );
|
|
addCrateType( "airdrop_assault_odds", "w", 30, ::killstreakCrateThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_trophy", "heavy_exosuit_rockets", "heavy_exosuit_eject" );
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_reinforcement_common", "a", 100, ::reinforcementCrateKillstreakThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian" );
|
|
addCrateType( "airdrop_reinforcement_common", "b", 100, ::reinforcementCrateKillstreakThink, &"MP_UAV_PICKUP", "uav", "uav_enemy_direction" );
|
|
addCrateType( "airdrop_reinforcement_common", "c", 100, ::reinforcementCrateKillstreakThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_assist_points" );
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_reinforcement_uncommon", "a", 100, ::reinforcementCrateKillstreakThink, &"MP_EMP_PICKUP", "emp" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "b", 100, ::reinforcementCrateKillstreakThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "c", 100, ::reinforcementCrateKillstreakThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_rippable", "sentry_rocket_turret" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "d", 100, ::reinforcementCrateKillstreakThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_chem", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "e", 100, ::reinforcementCrateKillstreakThink, &"MP_UAV_PICKUP", "uav", "uav_scrambler", "uav_increased_time" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "f", 100, ::reinforcementCrateKillstreakThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_paint_grenade", "recon_ugv_assist_points" );
|
|
|
|
addCrateType( "airdrop_reinforcement_uncommon", "g", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_EXO_BATTERY", "specialty_extended_battery" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "h", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_LOWPROFILE", "specialty_class_lowprofile" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "j", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_FLAKJACKET", "specialty_class_flakjacket" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "k", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_LIGHTWEIGHT", "specialty_class_lightweight" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "l", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_BLINDEYE", "specialty_class_blindeye" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "m", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_COLDBLOODED", "specialty_class_coldblooded" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "n", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_PERIPHERALS", "specialty_class_peripherals" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "o", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_FASTHANDS", "specialty_class_fasthands" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "p", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_DEXTERITY", "specialty_class_dexterity" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "r", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_EXO_BLASTSUPPRESSOR", "specialty_exo_blastsuppressor" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "s", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_HARDWIRED", "specialty_class_hardwired" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "t", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_TOUGHNESS", "specialty_class_toughness" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "u", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_SCAVENGER", "specialty_class_scavenger" );
|
|
addCrateType( "airdrop_reinforcement_uncommon", "v", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_HARDLINE", "specialty_class_hardline" );
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_reinforcement_rare", "a", 100, ::reinforcementCrateKillstreakThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_radar" );
|
|
addCrateType( "airdrop_reinforcement_rare", "b", 100, ::reinforcementCrateKillstreakThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_turret" );
|
|
addCrateType( "airdrop_reinforcement_rare", "c", 100, ::reinforcementCrateKillstreakThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_flares" );
|
|
addCrateType( "airdrop_reinforcement_rare", "d", 100, ::reinforcementCrateKillstreakThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_ai_attack", "warbird_flares" );
|
|
addCrateType( "airdrop_reinforcement_rare", "e", 100, ::reinforcementCrateKillstreakThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_width", "orbital_strike_laser_duration" );
|
|
addCrateType( "airdrop_reinforcement_rare", "f", 100, ::reinforcementCrateKillstreakThink, &"MP_UAV_PICKUP", "uav", "uav_scrambler", "uav_increased_time", "uav_paint_outline" );
|
|
addCrateType( "airdrop_reinforcement_rare", "g", 100, ::reinforcementCrateKillstreakThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_paint_grenade", "recon_ugv_assist_points", "recon_ugv_stun" );
|
|
|
|
addCrateType( "airdrop_reinforcement_rare", "h", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_EXO_BATTERY", "specialty_extended_battery" );
|
|
addCrateType( "airdrop_reinforcement_rare", "i", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_LOWPROFILE", "specialty_class_lowprofile" );
|
|
addCrateType( "airdrop_reinforcement_rare", "k", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_FLAKJACKET", "specialty_class_flakjacket" );
|
|
addCrateType( "airdrop_reinforcement_rare", "l", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_LIGHTWEIGHT", "specialty_class_lightweight" );
|
|
addCrateType( "airdrop_reinforcement_rare", "m", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_BLINDEYE", "specialty_class_blindeye" );
|
|
addCrateType( "airdrop_reinforcement_rare", "n", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_COLDBLOODED", "specialty_class_coldblooded" );
|
|
addCrateType( "airdrop_reinforcement_rare", "o", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_PERIPHERALS", "specialty_class_peripherals" );
|
|
addCrateType( "airdrop_reinforcement_rare", "p", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_FASTHANDS", "specialty_class_fasthands" );
|
|
addCrateType( "airdrop_reinforcement_rare", "q", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_DEXTERITY", "specialty_class_dexterity" );
|
|
addCrateType( "airdrop_reinforcement_rare", "s", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_EXO_BLASTSUPPRESSOR", "specialty_exo_blastsuppressor" );
|
|
addCrateType( "airdrop_reinforcement_rare", "t", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_HARDWIRED", "specialty_class_hardwired" );
|
|
addCrateType( "airdrop_reinforcement_rare", "u", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_TOUGHNESS", "specialty_class_toughness" );
|
|
addCrateType( "airdrop_reinforcement_rare", "v", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_SCAVENGER", "specialty_class_scavenger" );
|
|
addCrateType( "airdrop_reinforcement_rare", "w", 100, ::reinforcementCrateSpecialtyThink, &"PERKS_HARDLINE", "specialty_class_hardline" );
|
|
|
|
// dropType crateType crateWeight crateFunc hint string streak ref module 1 module 2 module 3
|
|
addCrateType( "airdrop_reinforcement_practice", "a", 168, ::reinforcementCrateKillstreakThink, &"MP_SENTRY_PICKUP", "remote_mg_sentry_turret", "sentry_guardian", "sentry_rippable", "sentry_rocket_turret" );
|
|
addCrateType( "airdrop_reinforcement_practice", "b", 168, ::reinforcementCrateKillstreakThink, &"MP_MISSILE_STRIKE_PICKUP", "missile_strike", "missile_strike_extra_1" );
|
|
addCrateType( "airdrop_reinforcement_practice", "c", 168, ::reinforcementCrateKillstreakThink, &"MP_RECON_UGV_PICKUP", "recon_ugv", "recon_ugv_paint_grenade", "recon_ugv_assist_points" );
|
|
addCrateType( "airdrop_reinforcement_practice", "d", 98, ::reinforcementCrateKillstreakThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_beam" );
|
|
addCrateType( "airdrop_reinforcement_practice", "e", 98, ::reinforcementCrateKillstreakThink, &"MP_ORBITAL_STRIKE_LASER_PICKUP", "orbital_strike_laser", "orbital_strike_laser_width", "orbital_strike_laser_duration" );
|
|
addCrateType( "airdrop_reinforcement_practice", "f", 100, ::reinforcementCrateKillstreakThink, &"MP_UAV_PICKUP", "uav", "uav_enemy_direction", "uav_orbit" );
|
|
addCrateType( "airdrop_reinforcement_practice", "g", 100, ::reinforcementCrateKillstreakThink, &"MP_UAV_PICKUP", "uav", "uav_scrambler", "uav_increased_time", "uav_paint_outline" );
|
|
addCrateType( "airdrop_reinforcement_practice", "h", 40, ::reinforcementCrateKillstreakThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_rockets", "warbird_coop_offensive" );
|
|
addCrateType( "airdrop_reinforcement_practice", "i", 40, ::reinforcementCrateKillstreakThink, &"MP_WARBIRD_PICKUP", "warbird", "warbird_ai_attack", "warbird_flares", "warbird_time" );
|
|
addCrateType( "airdrop_reinforcement_practice", "j", 30, ::reinforcementCrateKillstreakThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_mg", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_reinforcement_practice", "k", 30, ::reinforcementCrateKillstreakThink, &"MP_GROUND_ASSAULT_DRONE_PICKUP", "assault_ugv", "assault_ugv_ai", "assault_ugv_rockets" );
|
|
addCrateType( "airdrop_reinforcement_practice", "l", 20, ::reinforcementCrateKillstreakThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_turret", "orbitalsupport_coop_offensive","orbitalsupport_ammo" );
|
|
addCrateType( "airdrop_reinforcement_practice", "m", 20, ::reinforcementCrateKillstreakThink, &"MP_ORBITALSUPPORT_PICKUP", "orbitalsupport", "orbitalsupport_rockets", "orbitalsupport_flares", "orbitalsupport_time" );
|
|
addCrateType( "airdrop_reinforcement_practice", "n", 20, ::reinforcementCrateKillstreakThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_flares" );
|
|
addCrateType( "airdrop_reinforcement_practice", "o", 20, ::reinforcementCrateKillstreakThink, &"MP_AIRSTRIKE_PICKUP", "strafing_run_airstrike", "strafing_run_airstrike_stealth" );
|
|
addCrateType( "airdrop_reinforcement_practice", "p", 10, ::reinforcementCrateKillstreakThink, &"MP_EMP_PICKUP", "emp", "emp_assist", "emp_flash" );
|
|
addCrateType( "airdrop_reinforcement_practice", "q", 10, ::reinforcementCrateKillstreakThink, &"MP_EMP_PICKUP", "emp", "emp_streak_kill", "emp_equipment_kill", "emp_time_1" );
|
|
addCrateType( "airdrop_reinforcement_practice", "r", 10, ::reinforcementCrateKillstreakThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_radar", "heavy_exosuit_punch" );
|
|
addCrateType( "airdrop_reinforcement_practice", "s", 10, ::reinforcementCrateKillstreakThink, &"MP_HEAVY_EXO_PICKUP", "heavy_exosuit", "heavy_exosuit_trophy", "heavy_exosuit_rockets", "heavy_exosuit_eject" );
|
|
}
|
|
|
|
generateMaxWeightedCrateValue()
|
|
{
|
|
foreach( dropType, dropTypeArray in level.crateTypes )
|
|
{
|
|
level.crateMaxVal[ dropType ] = 0;
|
|
foreach( crateType in dropTypeArray )
|
|
{
|
|
type = crateType.type;
|
|
if( !level.crateTypes[ dropType ][ type ].raw_weight )
|
|
{
|
|
level.crateTypes[ dropType ][ type ].weight = level.crateTypes[ dropType ][ type ].raw_weight;
|
|
continue;
|
|
}
|
|
|
|
level.crateMaxVal[ dropType ] += level.crateTypes[ dropType ][ type ].raw_weight;
|
|
level.crateTypes[ dropType ][ type ].weight = level.crateMaxVal[ dropType ];
|
|
}
|
|
}
|
|
}
|
|
|
|
changeCrateWeight(dropType, crateType, crateWeight)
|
|
{
|
|
if(!IsDefined(level.crateTypes[ dropType ]) || !IsDefined(level.crateTypes[ dropType ][ crateType ]))
|
|
return;
|
|
|
|
level.crateTypes[ dropType ][ crateType ].raw_weight = crateWeight;
|
|
generateMaxWeightedCrateValue();
|
|
}
|
|
|
|
setAirDropCrateCollision( carePackageName )
|
|
{
|
|
airDropCrates = GetEntArray( carePackageName, "targetname" );
|
|
|
|
if( !IsDefined(airDropCrates) || (airDropCrates.size == 0 ) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
level.airDropCrateCollision = GetEnt( airDropCrates[0].target, "targetname" );
|
|
|
|
foreach( crate in airDropCrates )
|
|
{
|
|
crate deleteCrate();
|
|
}
|
|
}
|
|
|
|
addCrateType( dropType, crateType, crateWeight, crateFunc, hintString, streakRef, moduleRef1, moduleRef2, moduleRef3 )
|
|
{
|
|
if( !IsDefined(crateType) )
|
|
return;
|
|
|
|
level.crateTypes[ dropType ][ crateType ] = SpawnStruct();
|
|
|
|
level.crateTypes[ dropType ][ crateType ].dropType = dropType;
|
|
level.crateTypes[ dropType ][ crateType ].type = crateType;
|
|
level.crateTypes[ dropType ][ crateType ].raw_weight = crateWeight;
|
|
level.crateTypes[ dropType ][ crateType ].weight = crateWeight;
|
|
level.crateTypes[ dropType ][ crateType ].func = crateFunc;
|
|
level.crateTypes[ dropType ][ crateType ].streakRef = streakRef;
|
|
level.crateTypes[ dropType ][ crateType ].modules = [];
|
|
level.crateTypes[ dropType ][ crateType ].modules[ level.crateTypes[ dropType ][ crateType ].modules.size ] = moduleRef1;
|
|
level.crateTypes[ dropType ][ crateType ].modules[ level.crateTypes[ dropType ][ crateType ].modules.size ] = moduleRef2;
|
|
level.crateTypes[ dropType ][ crateType ].modules[ level.crateTypes[ dropType ][ crateType ].modules.size ] = moduleRef3;
|
|
|
|
if( IsDefined( hintString ) )
|
|
game[ "strings" ][ dropType + crateType + "_hint" ] = hintString;
|
|
}
|
|
|
|
getStreakForCrate( dropType, crateType )
|
|
{
|
|
if ( IsDefined( level.crateTypes[ dropType ] ) && IsDefined( level.crateTypes[ dropType ][ crateType ] ) && IsDefined( level.crateTypes[ dropType ][ crateType ].streakRef ) )
|
|
return level.crateTypes[ dropType ][ crateType ].streakRef;
|
|
|
|
return crateType;
|
|
}
|
|
|
|
getModulesForCrate( dropType, crateType )
|
|
{
|
|
if ( IsDefined( level.customKillstreakCrateModules ) )
|
|
return [[level.customKillstreakCrateModules]]( dropType, crateType );
|
|
|
|
return level.crateTypes[ dropType ][ crateType ].modules;
|
|
}
|
|
|
|
getRandomCrateType( dropType, excludeCrateTypes )
|
|
{
|
|
/#
|
|
if ( GetDvar( "scr_setnextkillstreak", "" ) != "" )
|
|
{
|
|
killstreak = GetDvar( "scr_setnextkillstreak" );
|
|
SetDvar( "scr_setnextkillstreak", "" );
|
|
|
|
foreach( crateType in level.crateTypes[ dropType ] )
|
|
{
|
|
type = crateType.type;
|
|
if ( level.crateTypes[ dropType ][ type ].streakRef == killstreak )
|
|
return type;
|
|
}
|
|
}
|
|
#/
|
|
if ( GetDvar ( "g_gametype" ) != "horde" )
|
|
{
|
|
typeHasMapKillstreak = IsDefined( level.mapKillStreak ) && isDefined(level.crateTypes[dropType][level.mapKillStreak]);
|
|
canSpawnMapKillStreak = IsDefined(level.mapKillstreakAutoDropIndex) && level.numDropCrates >= level.mapKillstreakAutoDropIndex;
|
|
if ( typeHasMapKillstreak && canSpawnMapKillStreak )
|
|
{
|
|
level.mapKillstreakAutoDropIndex = undefined;
|
|
return level.mapKillStreak;
|
|
}
|
|
}
|
|
|
|
value = RandomInt( level.crateMaxVal[ dropType ] );
|
|
selectedCrateType = undefined;
|
|
|
|
dropTypes = level.crateTypes[ dropType ];
|
|
if( isDefined( excludeCrateTypes ) )
|
|
{
|
|
AssertEx( isArray( excludeCrateTypes ), "excludeCrateTypes must be an array" );
|
|
dropTypeArray = level.crateTypes[ dropType ];
|
|
foreach( ent in dropTypeArray )
|
|
{
|
|
if( crateTypeIsExcluded( ent.type, excludeCrateTypes ) )
|
|
{
|
|
dropTypeArray = special_array_remove( dropTypeArray, ent );
|
|
}
|
|
}
|
|
dropTypes = dropTypeArray;
|
|
}
|
|
|
|
foreach( crateType in dropTypes )
|
|
{
|
|
type = crateType.type;
|
|
if( !level.crateTypes[ dropType ][ type ].weight )
|
|
continue;
|
|
|
|
selectedCrateType = type;
|
|
|
|
if( level.crateTypes[ dropType ][ type ].weight > value )
|
|
break;
|
|
}
|
|
|
|
return( selectedCrateType );
|
|
}
|
|
|
|
crateTypeIsExcluded( type, excludeCrateTypes )
|
|
{
|
|
foreach( excludeType in excludeCrateTypes )
|
|
{
|
|
if( excludeType == type )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
special_array_remove( array, remove )
|
|
{
|
|
new_array = [];
|
|
foreach( ent in array )
|
|
{
|
|
if( ent != remove )
|
|
{
|
|
new_array[ent.type] = ent;
|
|
}
|
|
}
|
|
return new_array;
|
|
}
|
|
|
|
|
|
getCrateTypeForDropType( dropType, excludedCrateTypes )
|
|
{
|
|
switch ( dropType )
|
|
{
|
|
case "airdrop_assault":
|
|
case "airdrop_assault_odds":
|
|
default:
|
|
return getRandomCrateType( dropType, excludedCrateTypes );
|
|
}
|
|
}
|
|
|
|
/**********************************************************
|
|
* crate functions
|
|
***********************************************************/
|
|
|
|
deleteOnOwnerDeath( owner )
|
|
{
|
|
// wait ( 0.25 );
|
|
self linkTo( owner, "tag_origin", (0,0,0), (0,0,0) );
|
|
|
|
owner waittill ( "death" );
|
|
|
|
self delete();
|
|
}
|
|
|
|
|
|
crateTeamModelUpdater() // self == crate team model (the logo)
|
|
{
|
|
self endon ( "death" );
|
|
|
|
self hide();
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( player.team != "spectator" )
|
|
self ShowToPlayer( player );
|
|
}
|
|
|
|
for ( ;; )
|
|
{
|
|
level waittill ( "joined_team" );
|
|
|
|
self hide();
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( player.team != "spectator" )
|
|
self ShowToPlayer( player );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
crateModelTeamUpdater( showForTeam, showToSpectator ) // self == crate model (friendly or enemy)
|
|
{
|
|
self endon ( "death" );
|
|
|
|
self hide();
|
|
|
|
foreach ( player in level.players )
|
|
{
|
|
if( ( player.team == showForTeam ) || ( showToSpectator && ( player.team == "spectator" ) ) )
|
|
self ShowToPlayer( player );
|
|
}
|
|
|
|
for ( ;; )
|
|
{
|
|
level waittill_any( "joined_team", "joined_spectators" );
|
|
|
|
self hide();
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( ( player.team == showForTeam ) || ( showToSpectator && ( player.team == "spectator" ) ) )
|
|
self ShowToPlayer( player );
|
|
}
|
|
}
|
|
}
|
|
|
|
// for FFA
|
|
crateModelPlayerUpdater( owner, friendly ) // self == crate model (friendly or enemy)
|
|
{
|
|
self endon ( "death" );
|
|
|
|
self hide();
|
|
|
|
foreach ( player in level.players )
|
|
{
|
|
if( friendly && IsDefined( owner ) && player != owner )
|
|
continue;
|
|
if( !friendly && IsDefined( owner ) && player == owner )
|
|
continue;
|
|
|
|
self ShowToPlayer( player );
|
|
}
|
|
|
|
for ( ;; )
|
|
{
|
|
level waittill ( "joined_team" );
|
|
|
|
self hide();
|
|
foreach ( player in level.players )
|
|
{
|
|
if( friendly && IsDefined( owner ) && player != owner )
|
|
continue;
|
|
if( !friendly && IsDefined( owner ) && player == owner )
|
|
continue;
|
|
|
|
self ShowToPlayer( player );
|
|
}
|
|
}
|
|
}
|
|
|
|
crateUseTeamUpdater( team )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
for ( ;; )
|
|
{
|
|
setUsableByTeam( team );
|
|
|
|
level waittill ( "joined_team" );
|
|
|
|
}
|
|
}
|
|
|
|
crateUseJuggernautUpdater()
|
|
{
|
|
streakRef = getStreakForCrate( self.dropType, self.crateType );
|
|
if ( !isSubStr( streakRef, "juggernaut" ) )
|
|
return;
|
|
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
for ( ;; )
|
|
{
|
|
level waittill ( "juggernaut_equipped", player );
|
|
|
|
self disablePlayerUse( player );
|
|
self thread crateUsePostJuggernautUpdater( player );
|
|
}
|
|
}
|
|
|
|
crateUsePostJuggernautUpdater( player )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
player endon( "disconnect" );
|
|
|
|
player waittill( "death" );
|
|
self enablePlayerUse( player );
|
|
}
|
|
|
|
/*
|
|
=============
|
|
///ScriptDocBegin
|
|
"Name: createAirDropCrate( <owner> , <dropType> , <crateType> , <startPos> , <startAngles> )"
|
|
"Summary: "
|
|
"Module: Entity"
|
|
"CallOn: An entity"
|
|
"MandatoryArg: <owner>: owner of the crate"
|
|
"MandatoryArg: <dropType>: assault, trap, etc"
|
|
"MandatoryArg: <crateType>: uav, counter-uav, predator, etc"
|
|
"MandatoryArg: <startPos>: vector origin"
|
|
"OptionalArg: <startAngles>: vector angles"
|
|
"OptionalArg: <alreadyTrapped>: start as a trap to enemies even though it is normal to allies"
|
|
"OptionalArg: <setupCollision>: setup collision immediately, default to true"
|
|
"Example: dropCrate = createAirDropCrate( self.owner, dropType, crateType, startPos );"
|
|
"SPMP: MP"
|
|
///ScriptDocEnd
|
|
=============
|
|
*/
|
|
createAirDropCrate( owner, dropType, crateType, startPos, startAngles, alreadyTrapped, setupCollision )
|
|
{
|
|
if ( !IsDefined( startAngles ) )
|
|
startAngles = ( 0, 0, 0 );
|
|
|
|
if ( !IsDefined( alreadyTrapped ) )
|
|
alreadyTrapped = false;
|
|
|
|
if ( !IsDefined( setupCollision ) )
|
|
setupCollision = true;
|
|
|
|
dropCrate = spawn( "script_model", startPos );
|
|
dropCrate.angles = startAngles; //TODO: applying angles after the spawn() function call isn't fast enough. Need code help.
|
|
|
|
dropCrate.curProgress = 0;
|
|
dropCrate.useTime = 0;
|
|
dropCrate.useRate = 0;
|
|
dropCrate.team = self.team;
|
|
|
|
if ( isDefined( owner ) )
|
|
dropCrate.owner = owner;
|
|
else
|
|
dropCrate.owner = undefined;
|
|
|
|
dropCrate.crateType = crateType;
|
|
dropCrate.dropType = dropType;
|
|
dropCrate.targetname = "care_package";
|
|
dropCrate.isTrap = alreadyTrapped;
|
|
|
|
if ( dropCrate.team == "any" )
|
|
{
|
|
dropCrate setModel("orbital_carepackage_pod_01_ai");
|
|
//Need a friendly model and it need to not use cloned brush collision to work with check for trigger_hurt
|
|
dropCrate.friendlyModel = spawn( "script_model", dropCrate.origin );
|
|
dropCrate.friendlyModel SetModel("tag_origin");
|
|
dropCrate.friendlyModel thread deleteOnOwnerDeath( dropCrate );
|
|
}
|
|
else
|
|
{
|
|
dropCrate setModel( maps\mp\gametypes\_teams::getTeamCrateModel( dropCrate.team ) );
|
|
dropCrate thread crateTeamModelUpdater();
|
|
|
|
friendlyModelName = "orbital_carepackage_pod_01_ai";
|
|
enemyModelName = "orbital_carepackage_pod_01_clr_01_ai";
|
|
if ( crateType == "booby_trap" )
|
|
{
|
|
friendlyModelName = "orbital_carepackage_pod_01_logo_trap_ai";
|
|
dropCrate thread trap_createBombSquadModel();
|
|
}
|
|
else if ( alreadyTrapped )
|
|
{
|
|
dropCrate thread trap_createBombSquadModel();
|
|
}
|
|
|
|
dropCrate.friendlyModel = spawn( "script_model", startPos );
|
|
dropCrate.friendlyModel setModel( friendlyModelName );
|
|
dropCrate.friendlyModel.parentCrate = dropCrate;
|
|
dropCrate.friendlyModel NotSolid();
|
|
dropCrate.enemyModel = spawn( "script_model", startPos );
|
|
dropCrate.enemyModel setModel( enemyModelName );
|
|
dropCrate.enemyModel.parentCrate = dropCrate;
|
|
dropCrate.enemyModel NotSolid();
|
|
|
|
dropCrate.friendlyModel thread deleteOnOwnerDeath( dropCrate );
|
|
if( level.teambased )
|
|
dropCrate.friendlyModel thread crateModelTeamUpdater( dropCrate.team, true );
|
|
else
|
|
dropCrate.friendlyModel thread crateModelPlayerUpdater( owner, true );
|
|
|
|
dropCrate.enemyModel thread deleteOnOwnerDeath( dropCrate );
|
|
|
|
if( level.teambased )
|
|
dropCrate.enemyModel thread crateModelTeamUpdater( level.otherTeam[dropCrate.team], false );
|
|
else
|
|
dropCrate.enemyModel thread crateModelPlayerUpdater( owner, false );
|
|
}
|
|
|
|
dropCrate.inUse = false;
|
|
|
|
if ( setupCollision )
|
|
dropCrate CloneBrushmodelToScriptmodel( level.airDropCrateCollision );
|
|
|
|
dropCrate.killCamEnt = Spawn( "script_model", dropCrate.origin + CRATE_KILLCAM_OFFSET );
|
|
dropCrate.killCamEnt SetScriptMoverKillCam( "explosive" );
|
|
dropCrate.killCamEnt SetContents(0);
|
|
dropCrate.killCamEnt LinkTo( dropCrate );
|
|
|
|
level.numDropCrates++;
|
|
|
|
return dropCrate;
|
|
}
|
|
|
|
trap_createBombSquadModel() // self == crate
|
|
{
|
|
bombSquadModel = spawn( "script_model", self.origin );
|
|
bombSquadModel.angles = self.angles;
|
|
bombSquadModel hide();
|
|
|
|
bombSquadModel thread maps\mp\gametypes\_weapons::bombSquadVisibilityUpdater( self.owner );
|
|
bombSquadModel setModel( "orbital_carepackage_pod_01_ai_bombsquad" );
|
|
bombSquadModel linkTo( self );
|
|
bombSquadModel SetContents( 0 );
|
|
|
|
self waittill ( "death" );
|
|
|
|
bombSquadModel delete();
|
|
}
|
|
|
|
crateSetupHintStrings( hintString, secondaryHintString )
|
|
{
|
|
if ( IsDefined( secondaryHintString ) && IsDefined( self.owner ) )
|
|
{
|
|
self.ownerStringEnt = Spawn( "script_model", self.origin + ( 0, 0, 60 ) );
|
|
self.ownerStringEnt setCursorHint( "HINT_NOICON" );
|
|
self.ownerStringEnt setHintString( hintString );
|
|
self.ownerStringEnt SetSecondaryHintString( secondaryHintString );
|
|
|
|
self.otherStringEnt = Spawn( "script_model", self.origin + ( 0, 0, 60 ) );
|
|
self.otherStringEnt setCursorHint( "HINT_NOICON" );
|
|
self.otherStringEnt setHintString( hintString );
|
|
}
|
|
else
|
|
{
|
|
self setCursorHint( "HINT_NOICON" );
|
|
self setHintString( hintString );
|
|
}
|
|
}
|
|
|
|
onPlayerConnectHintString( otherStringEnt, ownerStringEnt )
|
|
{
|
|
otherStringEnt endon( "death" );
|
|
ownerStringEnt endon( "death" );
|
|
|
|
while ( true )
|
|
{
|
|
level waittill( "connected", player );
|
|
|
|
player thread onPlayerSpawnedHintString( otherStringEnt, ownerStringEnt );
|
|
}
|
|
}
|
|
|
|
onPlayerSpawnedHintString( otherStringEnt, ownerStringEnt )
|
|
{
|
|
otherStringEnt endon( "death" );
|
|
ownerStringEnt endon( "death" );
|
|
|
|
self waittill( "spawned" );
|
|
|
|
otherStringEnt EnablePlayerUse( self );
|
|
ownerStringEnt DisablePlayerUse( self );
|
|
}
|
|
|
|
// Setup of drop pod when it reaches the ground
|
|
crateSetupForUse( mode, icons )
|
|
{
|
|
if( IsDefined ( level.isHorde ) && level.isHorde )
|
|
{
|
|
self waittill ( "drop_pod_cleared" );
|
|
}
|
|
|
|
if ( IsDefined( self.ownerStringEnt ) )
|
|
{
|
|
self.ownerStringEnt MakeUsable();
|
|
self.otherStringEnt MakeUsable();
|
|
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( player != self.owner )
|
|
{
|
|
self.ownerStringEnt DisablePlayerUse( player );
|
|
self.otherStringEnt EnablePlayerUse( player );
|
|
}
|
|
else
|
|
{
|
|
self.otherStringEnt DisablePlayerUse( player );
|
|
self.ownerStringEnt EnablePlayerUse( player );
|
|
}
|
|
}
|
|
|
|
thread onPlayerConnectHintString( self.otherStringEnt, self.ownerStringEnt );
|
|
}
|
|
else
|
|
{
|
|
self MakeUsable();
|
|
}
|
|
|
|
self.mode = mode;
|
|
|
|
if ( self.team == "any" )
|
|
{
|
|
curObjID = maps\mp\gametypes\_gameobjects::getNextObjID();
|
|
objective_add( curObjID, "invisible", (0,0,0) );
|
|
objective_position( curObjID, self.origin );
|
|
objective_state( curObjID, "active" );
|
|
|
|
shaderName = "compass_objpoint_ammo_friendly";
|
|
objective_icon( curObjID, shaderName );
|
|
|
|
Objective_Team( curObjID, "none");
|
|
|
|
self.objIdFriendly = curObjID;
|
|
}
|
|
else
|
|
{
|
|
//setup owner team
|
|
if ( level.teamBased || IsDefined( self.owner ) )
|
|
{
|
|
curObjID = maps\mp\gametypes\_gameobjects::getNextObjID();
|
|
objective_add( curObjID, "invisible", (0,0,0) );
|
|
objective_position( curObjID, self.origin );
|
|
objective_state( curObjID, "active" );
|
|
|
|
shaderName = "compass_objpoint_ammo_friendly";
|
|
if( mode == "trap" )
|
|
shaderName = "compass_objpoint_trap_friendly";
|
|
objective_icon( curObjID, shaderName );
|
|
|
|
if ( !level.teamBased && IsDefined( self.owner ) )
|
|
Objective_PlayerTeam( curObjId, self.owner GetEntityNumber() );
|
|
else
|
|
Objective_Team( curObjID, self.team );
|
|
|
|
self.objIdFriendly = curObjID;
|
|
}
|
|
|
|
if( ! ( IsDefined ( level.isHorde ) && level.isHorde ) )
|
|
{
|
|
if ( !IsDefined( self.owner ) || !( IsDefined( self.moduleHide ) && self.moduleHide ) )
|
|
{
|
|
curObjID = maps\mp\gametypes\_gameobjects::getNextObjID();
|
|
objective_add( curObjID, "invisible", (0,0,0) );
|
|
objective_position( curObjID, self.origin );
|
|
objective_state( curObjID, "active" );
|
|
objective_icon( curObjID, "compass_objpoint_ammo_enemy" );
|
|
|
|
if ( !level.teamBased && IsDefined( self.owner ) )
|
|
Objective_PlayerEnemyTeam( curObjId, self.owner GetEntityNumber() );
|
|
else
|
|
Objective_Team( curObjID, level.otherTeam[self.team] );
|
|
|
|
self.objIdEnemy = curObjID;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( self.team == "any" )
|
|
{
|
|
foreach(team in level.teamNameList)
|
|
{
|
|
if( isDefined( icons ) && isArray( icons ) )
|
|
{
|
|
self setHeadIcon_multiple( team, icons );
|
|
}
|
|
else
|
|
self maps\mp\_entityheadIcons::setHeadIcon( team, icons, (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
}
|
|
}
|
|
else if ( mode == "trap" )
|
|
{
|
|
self thread crateUseTeamUpdater( getOtherTeam( self.team ) );
|
|
}
|
|
else
|
|
{
|
|
self thread crateUseTeamUpdater();
|
|
|
|
streakRef = getStreakForCrate( self.dropType, self.crateType );
|
|
if ( isSubStr( streakRef, "juggernaut" ) )
|
|
{
|
|
foreach ( player in level.players )
|
|
if ( player isJuggernaut() )
|
|
self thread crateUsePostJuggernautUpdater( player );
|
|
}
|
|
|
|
if ( level.teamBased )
|
|
{
|
|
if( isDefined( icons ) && isArray( icons ) )
|
|
{
|
|
self setHeadIcon_multiple( self.team, icons );
|
|
}
|
|
else
|
|
self maps\mp\_entityheadIcons::setHeadIcon( self.team, icons, (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
}
|
|
else if ( IsDefined( self.owner ) )
|
|
{
|
|
if( isDefined( icons ) && isArray( icons ) )
|
|
{
|
|
self setHeadIcon_multiple( self.owner, icons );
|
|
}
|
|
else
|
|
self maps\mp\_entityheadIcons::setHeadIcon( self.owner, icons, (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
}
|
|
}
|
|
|
|
self thread crateUseJuggernautUpdater();
|
|
}
|
|
|
|
setHeadIcon_multiple( showTo, icons )
|
|
{
|
|
offset = 10;
|
|
i = 0;
|
|
self.iconEnts = [];
|
|
foreach( icon in icons )
|
|
{
|
|
self.iconEnts[ icon ] = self spawn_tag_origin();
|
|
self.iconEnts[ icon ] maps\mp\_entityheadIcons::setHeadIcon( showTo, icon, (0,0,(CRATE_ICON_Z_OFFSET - 5 ) + (i*offset)), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
i++;
|
|
}
|
|
}
|
|
|
|
setUsableByTeam( team )
|
|
{
|
|
streakRef = getStreakForCrate( self.dropType, self.crateType );
|
|
|
|
foreach ( player in level.players )
|
|
{
|
|
if ( isSubStr( streakRef, "juggernaut" ) && player isJuggernaut() )
|
|
{
|
|
self DisablePlayerUse( player );
|
|
}
|
|
else if ( !level.teamBased && self.mode == "trap" )
|
|
{
|
|
if ( IsDefined( self.owner ) && player == self.owner )
|
|
self DisablePlayerUse( player );
|
|
else
|
|
self EnablePlayerUse( player );
|
|
}
|
|
else if ( !IsDefined( team ) || team == player.team )
|
|
self EnablePlayerUse( player );
|
|
else
|
|
self DisablePlayerUse( player );
|
|
}
|
|
}
|
|
|
|
physicsWaiter( dropType, crateType )
|
|
{
|
|
self waittill( "physics_finished" );
|
|
|
|
self.droppingToGround = false;
|
|
self thread [[ level.crateTypes[ dropType ][ crateType ].func ]]( dropType );
|
|
level thread dropTimeOut( self, self.owner, crateType );
|
|
|
|
killTriggers = getEntArray( "trigger_hurt", "classname" );
|
|
foreach ( trigger in killTriggers )
|
|
{
|
|
if ( self.friendlyModel isTouching( trigger ) )
|
|
{
|
|
self deleteCrate();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if( IsDefined(self.owner) && ( abs(self.origin[2] - self.owner.origin[2]) > 4000 ) )
|
|
{
|
|
self deleteCrate();
|
|
return;
|
|
}
|
|
|
|
if ( IsDefined(level.isZombieGame) && level.isZombieGame )
|
|
self DisconnectPaths();
|
|
|
|
// Moving platforms.
|
|
data = SpawnStruct();
|
|
data.deathOverrideCallback = ::movingPlatformDeathFunc;
|
|
data.touchingPlatformValid = ::movingPlatformTouchValid;
|
|
self thread maps\mp\_movers::handle_moving_platforms( data );
|
|
}
|
|
|
|
movingPlatformDeathFunc( data )
|
|
{
|
|
self deleteCrate( true, true );
|
|
}
|
|
|
|
movingPlatformTouchValid( platform )
|
|
{
|
|
return ( carepackageAndCarepackageValid( platform ) && carepackageAndGoliathValid( platform ) && carepackageAndPlatformValid( platform ) );
|
|
}
|
|
|
|
carepackageAndGoliathValid( platform )
|
|
{
|
|
return ( !IsDefined( self.targetname )|| !IsDefined( platform.crateType ) || self.targetname != "care_package" || platform.crateType != "juggernaut" );
|
|
}
|
|
|
|
carepackageAndCarepackageValid( platform )
|
|
{
|
|
return ( !IsDefined( self.targetname )|| !IsDefined( platform.targetname ) || self.targetname != "care_package" || platform.targetname != "care_package" );
|
|
}
|
|
|
|
carepackageAndPlatformValid( platform )
|
|
{
|
|
return ( !IsDefined( self.targetname ) || !IsDefined( platform.carepackageTouchValid ) || self.targetname != "care_package" || !platform.carepackageTouchValid );
|
|
}
|
|
|
|
|
|
//deletes if crate wasnt used after 90 seconds
|
|
dropTimeOut( dropCrate, owner, crateType )
|
|
{
|
|
if( IsDefined(level.noCrateTimeOut) && (level.noCrateTimeOut) )
|
|
return;
|
|
|
|
level endon ( "game_ended" );
|
|
dropCrate endon( "death" );
|
|
|
|
if ( dropCrate.dropType == "nuke_drop" )
|
|
return;
|
|
|
|
timeOut = 90.0;
|
|
if ( crateType == "supply" )
|
|
timeOut = 20.0;
|
|
|
|
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( timeOut );
|
|
|
|
while ( dropCrate.curProgress != 0 )
|
|
wait 1;
|
|
|
|
dropCrate deleteCrate( true, true );
|
|
}
|
|
|
|
|
|
/**********************************************************
|
|
* crate trigger functions
|
|
***********************************************************/
|
|
|
|
crateOtherCaptureThink( useText )
|
|
{
|
|
self endon( "captured" );
|
|
|
|
crate = self;
|
|
if ( IsDefined( self.otherStringEnt ) )
|
|
crate = self.otherStringEnt;
|
|
|
|
while ( isDefined( self ) )
|
|
{
|
|
crate waittill( "trigger", player );
|
|
|
|
if ( isDefined( self.owner ) && player == self.owner )
|
|
continue;
|
|
|
|
if ( player IsJumping() || ( IsDefined( player.exo_hover_on ) && player.exo_hover_on ) )
|
|
continue;
|
|
|
|
if ( !player IsOnGround() && !waitPlayerStuckOnCarepackageReturn( player ) )
|
|
continue;
|
|
|
|
if ( !self validateOpenConditions( player ) )
|
|
continue;
|
|
|
|
player.isCapturingCrate = true;
|
|
useEnt = self createUseEnt();
|
|
result = false;
|
|
if ( self.crateType == "booby_trap" )
|
|
{
|
|
result = useEnt useHoldThink( player, 500, useText );
|
|
}
|
|
else
|
|
{
|
|
result = useEnt useHoldThink( player, undefined, useText );
|
|
}
|
|
|
|
if ( isDefined( useEnt ) )
|
|
useEnt delete();
|
|
|
|
if ( !result )
|
|
{
|
|
if ( IsDefined(player) )
|
|
player.isCapturingCrate = false;
|
|
continue;
|
|
}
|
|
|
|
player.isCapturingCrate = false;
|
|
|
|
//If the player is entering the juggernaut, ensure they successfully do so without falling into last stand
|
|
if( IsDefined( level.isHorde ) && level.isHorde )
|
|
{
|
|
if( self.crateType == "juggernaut" && !( IsDefined(player.lastStand) && player.lastStand ) )
|
|
player SetDemiGod( true );
|
|
|
|
//If the player has fallen into last stand, leave the crate there
|
|
if( IsDefined(player.lastStand) && player.lastStand )
|
|
continue;
|
|
}
|
|
|
|
self notify ( "captured", player );
|
|
}
|
|
}
|
|
|
|
crateOwnerCaptureThink( useText )
|
|
{
|
|
self endon( "captured" );
|
|
|
|
if ( !IsDefined( self.owner ) )
|
|
return;
|
|
|
|
self.owner endon( "disconnect" );
|
|
|
|
crate = self;
|
|
if ( IsDefined( self.ownerStringEnt ) )
|
|
crate = self.ownerStringEnt;
|
|
|
|
useHoldTime = 500;
|
|
if ( IsDefined( self.modulePickup ) && self.modulePickup )
|
|
useHoldTime = 100;
|
|
|
|
while ( isDefined( self ) )
|
|
{
|
|
crate waittill( "trigger", player );
|
|
|
|
if ( isDefined( self.owner ) && player != self.owner )
|
|
continue;
|
|
|
|
if ( player IsJumping() || ( IsDefined( player.exo_hover_on ) && player.exo_hover_on ) )
|
|
continue;
|
|
|
|
if ( !player IsOnGround() && !waitPlayerStuckOnCarepackageReturn( player ) )
|
|
continue;
|
|
|
|
if ( !self validateOpenConditions( player ) )
|
|
continue;
|
|
|
|
player.isCapturingCrate = true;
|
|
if ( !useHoldThink( player, useHoldTime, useText ) )
|
|
{
|
|
player.isCapturingCrate = false;
|
|
continue;
|
|
}
|
|
|
|
player.isCapturingCrate = false;
|
|
|
|
//If the player is entering the juggernaut, ensure they successfully do so without falling into last stand
|
|
if( IsDefined( level.isHorde ) && level.isHorde )
|
|
{
|
|
if( self.crateType == "juggernaut" && !( IsDefined(player.lastStand) && player.lastStand ) )
|
|
player SetDemiGod( true );
|
|
|
|
//If the player has fallen into last stand, leave the crate there
|
|
if( IsDefined(player.lastStand) && player.lastStand )
|
|
continue;
|
|
}
|
|
|
|
self notify ( "captured", player );
|
|
}
|
|
}
|
|
|
|
|
|
waitPlayerStuckOnCarepackageReturn( player )
|
|
{
|
|
if ( player IsOnGround() )
|
|
return false;
|
|
|
|
TIME_UNTIL_STUCK = 200;
|
|
|
|
startOrg = player.origin;
|
|
stuckTimeStart = GetTime();
|
|
|
|
while ( IsDefined( player ) && isReallyAlive( player ) && !player IsOnGround() && startOrg == player.origin && player UseButtonPressed() )
|
|
{
|
|
curTimeButtonHeld = GetTime() - stuckTimeStart;
|
|
if ( curTimeButtonHeld >= TIME_UNTIL_STUCK )
|
|
return true;
|
|
|
|
waitframe();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
validateOpenConditions( opener )
|
|
{
|
|
currentWeapon = opener GetCurrentPrimaryWeapon();
|
|
|
|
if ( IsSubStr( currentWeapon, "turrethead" ) )
|
|
return true;
|
|
|
|
if( !(opener maps\mp\killstreaks\_killstreaks::canShuffleWithKillstreakWeapon()) )
|
|
return false;
|
|
|
|
if( IsDefined(opener.changingWeapon) && !(opener maps\mp\killstreaks\_killstreaks::canShuffleWithKillstreakWeapon()) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
killstreakCrateThink( dropType )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
streakRef = getStreakForCrate( dropType, self.crateType );
|
|
modules = getModulesForCrate( dropType, self.crateType );
|
|
|
|
canReroll = isDefined(self.owner) && ( self.owner _hasPerk( "specialty_highroller" ) || ( IsDefined( self.moduleRoll ) && self.moduleRoll ) );
|
|
|
|
secondaryHintString = undefined;
|
|
if ( canReroll )
|
|
secondaryHintString = &"MP_PACKAGE_REROLL";
|
|
|
|
crateHint = undefined;
|
|
if ( isDefined( game["strings"][dropType + self.crateType + "_hint"] ) )
|
|
crateHint = game["strings"][dropType + self.crateType + "_hint"];
|
|
else
|
|
crateHint = &"PLATFORM_GET_KILLSTREAK";
|
|
|
|
crateSetupHintStrings( crateHint, secondaryHintString );
|
|
crateSetupForUse( "all", maps\mp\killstreaks\_killstreaks::getKillstreakCrateIcon( streakRef, modules ) );
|
|
|
|
if ( IsDefined(self.owner) )
|
|
self thread crateOtherCaptureThink();
|
|
self thread crateOwnerCaptureThink();
|
|
if ( canReroll )
|
|
self thread crateOwnerDoubleTapThink();
|
|
|
|
if ( self.isTrap )
|
|
self crateTrapSetupKillcam();
|
|
|
|
for ( ;; )
|
|
{
|
|
self waittill ( "captured", player );
|
|
|
|
streakRef = getStreakForCrate( dropType, self.crateType );
|
|
modules = getModulesForCrate( dropType, self.crateType );
|
|
|
|
if ( isDefined( self.owner ) && player != self.owner )
|
|
{
|
|
if ( !level.teamBased || player.team != self.team )
|
|
{
|
|
if ( self.isTrap )
|
|
{
|
|
player thread detonateTrap( self, self.owner );
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
player thread maps\mp\_events::hijackerEvent( self.owner );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
self.owner thread maps\mp\_events::sharedEvent();
|
|
}
|
|
}
|
|
|
|
player playLocalSound( "orbital_pkg_use" );
|
|
|
|
slotIndex = player maps\mp\killstreaks\_killstreaks::getNextKillstreakSlotIndex( streakRef, false );
|
|
player thread maps\mp\gametypes\_hud_message::killstreakSplashNotify( streakRef, undefined, undefined, modules, slotIndex );
|
|
player thread maps\mp\killstreaks\_killstreaks::giveKillstreak( streakRef, false, false, self.owner, modules );
|
|
|
|
if( IsDefined(level.mapKillStreak) && (level.mapKillStreak == self.crateType) )
|
|
player thread maps\mp\_events::mapKillStreakEvent();
|
|
|
|
//If the player has stolen the care package and the player has the specialty_highroller Perk, spawn a trap crate replacement.
|
|
shouldDestroyPlayVFX = true;
|
|
shouldTrapPerk = ( player _hasPerk( "specialty_highroller" ) && ( !level.teamBased || player.team != self.team ) );
|
|
packageHasModuleTrap = IsDefined( self.moduleTrap ) && self.moduleTrap;
|
|
shouldTrapModule = ( packageHasModuleTrap && ( self.owner == player || ( level.teamBased && player.team == self.team ) ) );
|
|
if ( shouldTrapPerk || shouldTrapModule )
|
|
{
|
|
newTrapCrate = player createAirDropCrate( player, "booby_trap", "booby_trap", self.origin, self.angles );
|
|
if ( IsDefined( newTrapCrate.enemymodel ) )
|
|
newTrapCrate.enemymodel thread maps\mp\killstreaks\_orbital_carepackage::orbitalAnimate( true );
|
|
newTrapCrate thread boobyTrapCrateThink( self );
|
|
level thread dropTimeOut( newTrapCrate, newTrapCrate.owner, newTrapCrate.crateType );
|
|
shouldDestroyPlayVFX = false;
|
|
|
|
// Make sure models are made solid again so that missiles are blocked by them
|
|
if ( IsDefined( newTrapCrate.friendlyModel ) )
|
|
newTrapCrate.friendlyModel Solid();
|
|
if ( IsDefined( newTrapCrate.enemyModel ) )
|
|
newTrapCrate.enemyModel Solid();
|
|
}
|
|
|
|
self deleteCrate( shouldDestroyPlayVFX );
|
|
}
|
|
}
|
|
|
|
detonateTrap( crate, owner )
|
|
{
|
|
crate endon ( "death" );
|
|
|
|
location = crate.origin + ( 0, 0, 50 );
|
|
|
|
if ( level.teamBased )
|
|
crate maps\mp\_entityheadIcons::setHeadIcon( self.team, "specialty_trap_crate", (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
else
|
|
crate maps\mp\_entityheadIcons::setHeadIcon( self, "specialty_trap_crate", (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
|
|
thread play_sound_in_space( "orbital_pkg_trap_armed", location );
|
|
wait (1.0);
|
|
|
|
forward = ( location + ( 0, 0, 1 ) ) - location;
|
|
playfx ( getfx( "airdrop_crate_trap_explode" ), location, forward );
|
|
thread play_sound_in_space( "orbital_pkg_trap_detonate", location );
|
|
|
|
// remove collision before blowing up so it doesn't get in the way of RadiusDamage traces
|
|
if ( IsDefined( crate.friendlyModel ) )
|
|
crate.friendlyModel NotSolid();
|
|
if ( IsDefined( crate.enemyModel ) )
|
|
crate.enemyModel NotSolid();
|
|
|
|
if ( isDefined( owner ) )
|
|
crate.trapKillCamEnt RadiusDamage( location, 400, 300, 50, owner, "MOD_EXPLOSIVE", "airdrop_trap_explosive_mp" );
|
|
else
|
|
crate.trapKillCamEnt RadiusDamage( location, 400, 300, 50, undefined, "MOD_EXPLOSIVE", "airdrop_trap_explosive_mp" );
|
|
|
|
crate deleteCrate();
|
|
}
|
|
|
|
/*
|
|
=============
|
|
///ScriptDocBegin
|
|
"Name: deleteCrate( <playDestroyVFX> )"
|
|
"Summary: deletes a crate"
|
|
"Module: Entity"
|
|
"CallOn: a crate"
|
|
"OptionalArg: <playDestroyVFX>: bool - set to false if this crate is replaced by a booby trap. This will make the trap more sneaky."
|
|
"Example: crate deleteCrate();"
|
|
"SPMP: MP"
|
|
///ScriptDocEnd
|
|
=============
|
|
*/
|
|
deleteCrate( playDestroyVFX, playDeathSound )
|
|
{
|
|
if ( !IsDefined( playDestroyVFX ) )
|
|
{
|
|
playDestroyVFX = true;
|
|
}
|
|
|
|
if ( !IsDefined( playDeathSound ) )
|
|
playDeathSound = false;
|
|
|
|
if ( isDefined( self.objIdFriendly ) )
|
|
_objective_delete( self.objIdFriendly );
|
|
|
|
if ( isDefined( self.objIdEnemy ) )
|
|
{
|
|
_objective_delete( self.objIdEnemy );
|
|
}
|
|
|
|
if ( isDefined( self.trapKillcamEnt ) )
|
|
self.trapKillcamEnt delete();
|
|
|
|
if ( IsDefined( self.killCamEnt ) )
|
|
self.killCamEnt delete();
|
|
|
|
if ( IsDefined( self.ownerStringEnt ) )
|
|
self.ownerStringEnt Delete();
|
|
|
|
if ( IsDefined( self.otherStringEnt ) )
|
|
self.otherStringEnt Delete();
|
|
|
|
if ( isDefined( self.dropType ) )
|
|
{
|
|
if ( playDestroyVFX )
|
|
{
|
|
PlayFX( getfx( "ocp_death" ), self.origin );
|
|
}
|
|
|
|
if ( playDeathSound )
|
|
{
|
|
playSoundAtPos( self.origin, "orbital_pkg_self_destruct" );
|
|
}
|
|
}
|
|
|
|
if( isDefined( self.iconEnts ) )
|
|
{
|
|
foreach( icon_ent in self.iconEnts )
|
|
{
|
|
icon_ent delete();
|
|
}
|
|
}
|
|
|
|
self delete();
|
|
}
|
|
|
|
/**********************************************************
|
|
* Capture crate functions
|
|
***********************************************************/
|
|
useHoldThink( player, useTime, useText )
|
|
{
|
|
if ( IsPlayer( player ) )
|
|
player playerLinkTo( self );
|
|
else
|
|
player LinkTo( self );
|
|
player playerLinkedOffsetEnable();
|
|
|
|
if ( !player isJuggernaut() )
|
|
player _disableWeapon();
|
|
|
|
self thread useHoldThinkPlayerReset( player );
|
|
|
|
self.curProgress = 0;
|
|
self.inUse = true;
|
|
self.useRate = 0;
|
|
|
|
if ( isDefined( useTime ) )
|
|
{
|
|
if ( player _hasPerk( "specialty_unwrapper" ) && IsDefined( player.specialty_unwrapper_care_bonus ) )
|
|
{
|
|
useTime *= player.specialty_unwrapper_care_bonus;
|
|
}
|
|
self.useTime = useTime;
|
|
}
|
|
else
|
|
{
|
|
if ( player _hasPerk( "specialty_unwrapper" ) && IsDefined( player.specialty_unwrapper_care_bonus ) )
|
|
{
|
|
self.useTime = 3000 * player.specialty_unwrapper_care_bonus;
|
|
}
|
|
else
|
|
{
|
|
self.useTime = 3000;
|
|
}
|
|
}
|
|
|
|
if ( IsPlayer( player ) )
|
|
player thread personalUseBar( self, useText );
|
|
|
|
result = useHoldThinkLoop( player );
|
|
assert ( isDefined( result ) );
|
|
|
|
if ( !isDefined( self ) )
|
|
return false;
|
|
|
|
self notify( "useHoldThinkLoopDone" );
|
|
|
|
self.inUse = false;
|
|
self.curProgress = 0;
|
|
|
|
return ( result );
|
|
}
|
|
|
|
useHoldThinkPlayerReset( player )
|
|
{
|
|
player endon( "death" );
|
|
|
|
self waittill_any( "death", "captured", "useHoldThinkLoopDone" );
|
|
|
|
if ( isAlive( player ) )
|
|
{
|
|
if ( !player isJuggernaut() )
|
|
player _enableWeapon();
|
|
if ( player isLinked() )
|
|
player unlink();
|
|
}
|
|
}
|
|
|
|
personalUseBar( object, useText )
|
|
{
|
|
self endon( "disconnect" );
|
|
|
|
if ( isDefined( useText ) )
|
|
iprintlnbold( "Fixme @agersant " + useText );
|
|
self SetClientOmnvar( "ui_use_bar_text", 1 );
|
|
self SetClientOmnvar( "ui_use_bar_start_time", int( GetTime() ) );
|
|
|
|
lastRate = -1;
|
|
while ( isReallyAlive( self ) && isDefined( object ) && object.inUse && !level.gameEnded )
|
|
{
|
|
if ( lastRate != object.useRate )
|
|
{
|
|
if( object.curProgress > object.useTime)
|
|
object.curProgress = object.useTime;
|
|
if ( object.useRate > 0 )
|
|
{
|
|
now = GetTime();
|
|
current = object.curProgress / object.useTime;
|
|
endTime = now + ( 1 - current ) * ( object.useTime / object.useRate );
|
|
self SetClientOmnvar( "ui_use_bar_end_time", int( endTime ) );
|
|
}
|
|
lastRate = object.useRate;
|
|
}
|
|
wait ( 0.05 );
|
|
}
|
|
|
|
self SetClientOmnvar( "ui_use_bar_end_time", 0 );
|
|
|
|
}
|
|
|
|
isHordeLastStand( player )
|
|
{
|
|
return IsDefined( level.isHorde ) && level.isHorde && IsDefined( player.lastStand ) && player.lastStand;
|
|
}
|
|
|
|
useHoldThinkLoop( player )
|
|
{
|
|
while( !level.gameEnded && isDefined( self ) && isReallyAlive( player ) && !isHordeLastStand( player ) && player useButtonPressed() && self.curProgress < self.useTime )
|
|
{
|
|
self.curProgress += (50 * self.useRate);
|
|
|
|
if ( isDefined(self.objectiveScaler) )
|
|
self.useRate = 1 * self.objectiveScaler;
|
|
else
|
|
self.useRate = 1;
|
|
|
|
if ( self.curProgress >= self.useTime )
|
|
return ( isReallyAlive( player ) );
|
|
|
|
wait 0.05;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
isAirdropMarker( weaponName )
|
|
{
|
|
switch ( weaponName )
|
|
{
|
|
case "airdrop_marker_mp":
|
|
case "airdrop_mp":
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
createUseEnt()
|
|
{
|
|
useEnt = spawn( "script_origin", self.origin );
|
|
useEnt.curProgress = 0;
|
|
useEnt.useTime = 0;
|
|
useEnt.useRate = 3000;
|
|
useEnt.inUse = false;
|
|
|
|
useEnt thread deleteUseEnt( self );
|
|
|
|
return ( useEnt );
|
|
}
|
|
|
|
|
|
deleteUseEnt( owner )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
owner waittill ( "death" );
|
|
|
|
self delete();
|
|
}
|
|
|
|
/*
|
|
=============
|
|
///ScriptDocBegin
|
|
"Name: crateOwnerDoubleTapThink()"
|
|
"Summary: polls for a care package owner's double tap"
|
|
"Module: Entity"
|
|
"CallOn: a care package crate"
|
|
"Example: self thread crateOwnerDoubleTapThink();"
|
|
"SPMP: MP"
|
|
///ScriptDocEnd
|
|
=============
|
|
*/
|
|
crateOwnerDoubleTapThink()
|
|
{
|
|
self.packageHoldTimer = 0;
|
|
self.packageSingleTapped = false;
|
|
|
|
while( !level.gameEnded && isDefined( self ) )
|
|
{
|
|
if ( isReallyAlive( self.owner ) && DistanceSquared( self.origin, self.owner.origin ) < 10000 )
|
|
{
|
|
if ( self.owner useButtonPressed() )
|
|
{
|
|
self.packageHoldTimer++;
|
|
}
|
|
else
|
|
{
|
|
if ( self.packageHoldTimer > 0 )
|
|
{
|
|
if ( self.packageHoldTimer < 5 )
|
|
{
|
|
if ( self.packageSingleTapped == true )
|
|
{
|
|
//The owner has just double tapped the package.
|
|
self notify( "package_double_tap" );
|
|
previous_crateType = self.crateType;
|
|
reroll_attempts = 0;
|
|
while ( self.crateType == previous_crateType && reroll_attempts < 100 )
|
|
{
|
|
reroll_attempts++; //Try up to 100 rerolls because it wouldn't be very fun if you rerolled the exact same scorestreak.
|
|
self.crateType = getRandomCrateType( self.dropType );
|
|
}
|
|
|
|
streakRef = getStreakForCrate( self.dropType, self.crateType );
|
|
modules = getModulesForCrate( self.dropType, self.crateType );
|
|
|
|
hintString = game["strings"][self.dropType + self.crateType + "_hint"];
|
|
|
|
if( !IsDefined( hintString) )
|
|
hintString = &"PLATFORM_GET_KILLSTREAK";
|
|
|
|
if ( IsDefined( self.ownerStringEnt ) )
|
|
{
|
|
self.ownerStringEnt setHintString( hintString );
|
|
self.otherStringEnt setHintString( hintString );
|
|
self.ownerStringEnt SetSecondaryHintString( "" );
|
|
}
|
|
else
|
|
{
|
|
self setHintString( hintString );
|
|
self SetSecondaryHintString( "" );
|
|
}
|
|
if ( level.teamBased )
|
|
self maps\mp\_entityheadIcons::setHeadIcon( self.team, maps\mp\killstreaks\_killstreaks::getKillstreakCrateIcon( streakRef, modules ), (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
else if ( IsDefined( self.owner ) )
|
|
self maps\mp\_entityheadIcons::setHeadIcon( self.owner, maps\mp\killstreaks\_killstreaks::getKillstreakCrateIcon( streakRef, modules ), (0,0,CRATE_ICON_Z_OFFSET), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
|
|
|
|
self.owner PlayLocalSound( "orbital_pkg_reroll" );
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
self.packageSingleTapped = true;
|
|
self thread tapPackageThink();
|
|
}
|
|
}
|
|
self.packageHoldTimer = 0;
|
|
}
|
|
}
|
|
}
|
|
wait 0.05;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
///ScriptDocBegin
|
|
"Name: tapPackageThink()"
|
|
"Summary: polls for a double tap of the use button"
|
|
"Module: Entity"
|
|
"CallOn: a player"
|
|
"Example: player thread tapPackageThink();"
|
|
"SPMP: MP"
|
|
///ScriptDocEnd
|
|
=============
|
|
*/
|
|
tapPackageThink()
|
|
{
|
|
level endon( "game_ended" );
|
|
self endon( "death" );
|
|
self endon( "package_double_tap" );
|
|
|
|
wait( 0.2 );
|
|
|
|
self.packageSingleTapped = false;
|
|
}
|
|
|
|
|
|
/*
|
|
=============
|
|
///ScriptDocBegin
|
|
"Name: boobyTrapCrateThink( <originalCrate> )"
|
|
"Summary: handles a newly created booby trapped crate."
|
|
"Module: Entity"
|
|
"CallOn: a crate"
|
|
"MandatoryArg: <originalCrate>: the crate that this trap is replacing"
|
|
"Example: crate thread boobyTrapCrateThink( originalCrate );"
|
|
"SPMP: MP"
|
|
///ScriptDocEnd
|
|
=============
|
|
*/
|
|
boobyTrapCrateThink( originalCrate )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
streakRef = getStreakForCrate( originalCrate.dropType, originalCrate.crateType );
|
|
modules = getModulesForCrate( originalCrate.dropType, originalCrate.crateType );
|
|
|
|
crateIcon = maps\mp\killstreaks\_killstreaks::getKillstreakCrateIcon( streakRef, modules );
|
|
|
|
crateHint = undefined;
|
|
if ( isDefined( game["strings"][originalCrate.dropType + originalCrate.crateType + "_hint"] ) )
|
|
crateHint = game["strings"][originalCrate.dropType + originalCrate.crateType + "_hint"];
|
|
else
|
|
crateHint = &"PLATFORM_GET_KILLSTREAK";
|
|
|
|
crateSetupHintStrings( crateHint );
|
|
crateSetupForUse( "trap", crateIcon ); //TODO: need to use a different hint string depending on possession of specialty_highroller Perk.
|
|
|
|
self crateTrapSetupKillcam();
|
|
|
|
self thread crateOtherCaptureThink( originalCrate );
|
|
|
|
for ( ;; )
|
|
{
|
|
self waittill ( "captured", player );
|
|
|
|
player thread detonateTrap( self, self.owner );
|
|
}
|
|
}
|
|
|
|
crateTrapSetupKillcam( originalCrate )
|
|
{
|
|
result = BulletTrace( self.origin, self.origin + ( 0, 0, 90 ), false, self );
|
|
|
|
self.trapKillCamEnt = Spawn( "script_model", result[ "position" ] );
|
|
self.trapKillCamEnt SetContents(0);
|
|
self.trapKillCamEnt SetScriptMoverKillCam( "large explosive" );
|
|
}
|
|
|
|
//---REINFORCEMENTS---//
|
|
|
|
tryUseReinforcementCommon( lifeId, kID, modules )
|
|
{
|
|
return maps\mp\killstreaks\_orbital_carepackage::tryUseOrbitalCarePackage( lifeId, "airdrop_reinforcement_common", modules );
|
|
}
|
|
|
|
tryUseReinforcementUncommon( lifeId, kID, modules )
|
|
{
|
|
return maps\mp\killstreaks\_orbital_carepackage::tryUseOrbitalCarePackage( lifeId, "airdrop_reinforcement_uncommon", modules );
|
|
}
|
|
|
|
tryUseReinforcementRare( lifeId, kID, modules )
|
|
{
|
|
return maps\mp\killstreaks\_orbital_carepackage::tryUseOrbitalCarePackage( lifeId, "airdrop_reinforcement_rare", modules );
|
|
}
|
|
|
|
tryUseReinforcementPractice( lifeId, kID, modules )
|
|
{
|
|
return maps\mp\killstreaks\_orbital_carepackage::tryUseOrbitalCarePackage( lifeId, "airdrop_reinforcement_practice", modules );
|
|
}
|
|
|
|
reinforcementCrateKillstreakThink( dropType )
|
|
{
|
|
self killstreakCrateThink( dropType );
|
|
}
|
|
|
|
reinforcementCrateSpecialtyThink( dropType )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
perkRef = getPerkForCrate( dropType, self.crateType );
|
|
secondaryPerkRef = undefined;
|
|
|
|
if( dropType == "airdrop_reinforcement_rare" )
|
|
{
|
|
secondaryPerkRef = getSecondaryPerkForCrate( dropType );
|
|
}
|
|
|
|
icon = undefined;
|
|
|
|
if( isDefined( secondaryPerkRef ) )
|
|
{
|
|
primaryHint = game["strings"][dropType + self.crateType + "_hint"];
|
|
secondaryHint = getSecondaryPerkHintFromPerkRef( secondaryPerkRef );
|
|
|
|
if( isDefined( primaryHint ) && isDefined( secondaryHint ) )
|
|
self SetReinforcementHintStrings( primaryHint, secondaryHint );
|
|
else
|
|
crateSetupHintStrings( &"MP_PERK_PICKUP_GENERIC_MULTIPLE" );
|
|
|
|
icon = [];
|
|
icon[0] = getPerkCrateIcon( perkRef );
|
|
if( !isDefined( icon[0] ) )
|
|
icon[0] = "";
|
|
icon[1] = getPerkCrateIcon( secondaryPerkRef );
|
|
if( !isDefined( icon[1] ) )
|
|
icon[1] = "";
|
|
}
|
|
else
|
|
{
|
|
primaryHint = game["strings"][dropType + self.crateType + "_hint"];
|
|
if( isDefined( primaryHint ) )
|
|
self SetReinforcementHintStrings( primaryHint );
|
|
else
|
|
crateSetupHintStrings( &"MP_PERK_PICKUP_GENERIC" );
|
|
|
|
icon = getPerkCrateIcon( perkRef );
|
|
if( !isDefined( icon ) )
|
|
icon = "";
|
|
}
|
|
|
|
//hints already set above
|
|
crateSetupForUse( "all", icon );
|
|
|
|
if ( IsDefined(self.owner) )
|
|
self thread crateOtherCaptureThink();
|
|
|
|
self thread crateOwnerCaptureThink();
|
|
|
|
for ( ;; )
|
|
{
|
|
self waittill ( "captured", player );
|
|
|
|
if ( isDefined( self.owner ) && player != self.owner )
|
|
{
|
|
if ( !level.teamBased || player.team != self.team )
|
|
{
|
|
player thread maps\mp\_events::hijackerEvent( self.owner );
|
|
|
|
}
|
|
else
|
|
{
|
|
self.owner thread maps\mp\_events::sharedEvent();
|
|
}
|
|
}
|
|
|
|
player playLocalSound( "orbital_pkg_use" );
|
|
|
|
player apply_reinforcement_perk( perkRef );
|
|
|
|
perkIdx = int( TableLookupRowNum( "mp/perktable.csv", 1, perkRef ) );
|
|
|
|
player SetClientOmnvar( "ui_reinforcement_active_perk_1", perkIdx );
|
|
|
|
if( isDefined( secondaryPerkRef ) )
|
|
{
|
|
player apply_reinforcement_perk( secondaryPerkRef );
|
|
|
|
perkIdx = int( TableLookupRowNum( "mp/perktable.csv", 1, secondaryPerkRef ) );
|
|
|
|
player SetClientOmnvar( "ui_reinforcement_active_perk_2", perkIdx );
|
|
}
|
|
else
|
|
{
|
|
// clear second active perk
|
|
player SetClientOmnvar( "ui_reinforcement_active_perk_2", -1 );
|
|
}
|
|
|
|
self deleteCrate( true );
|
|
}
|
|
}
|
|
|
|
getPerkForCrate( dropType, crateType )
|
|
{
|
|
if ( IsDefined( level.crateTypes[ dropType ][ crateType ].streakRef ) )
|
|
return level.crateTypes[ dropType ][ crateType ].streakRef;
|
|
|
|
return crateType;
|
|
}
|
|
|
|
getSecondaryPerkForCrate( dropType )
|
|
{
|
|
if ( IsDefined( level.crateTypes[ dropType ] ) && IsDefined( level.crateTypes[ dropType ][ self.crateType ] ) )
|
|
{
|
|
excludeCrateTypes = [];
|
|
foreach( crate in level.crateTypes[ dropType ] )
|
|
{
|
|
if( !IsSubStr( crate.streakRef, "specialty_" ) )
|
|
excludeCrateTypes[excludeCrateTypes.size] = crate.type;
|
|
}
|
|
excludeCrateTypes[excludeCrateTypes.size] = self.crateType;
|
|
secondaryCrateType = getRandomCrateType( dropType, excludeCrateTypes );
|
|
if( isDefined( secondaryCrateType ) && isDefined( level.crateTypes[ dropType ][ secondaryCrateType ].streakRef ) )
|
|
{
|
|
return level.crateTypes[ dropType ][ secondaryCrateType ].streakRef;
|
|
}
|
|
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
getSecondaryPerkHintFromPerkRef( perkName )
|
|
{
|
|
crateHint = undefined;
|
|
|
|
if( isDefined( level.secondaryReinforcementHintText[perkName] ) )
|
|
crateHint = level.secondaryReinforcementHintText[perkName];
|
|
|
|
return crateHint;
|
|
}
|
|
|
|
getPerkCrateIcon( perkName )
|
|
{
|
|
perk_file = "mp/perktable.csv";
|
|
perkName_column = 1;
|
|
imageName_column = 11;
|
|
|
|
return tableLookup(perk_file, perkName_column, perkName, imageName_column );
|
|
}
|
|
|
|
apply_reinforcement_perk( perkName )
|
|
{
|
|
Assert( IsDefined( perkName ) );
|
|
|
|
if( perkName == "specialty_extended_battery" ) // Grants extra battery energy (currently 50%).
|
|
{
|
|
self givePerk( "specialty_extended_battery", false );
|
|
self givePerk( "specialty_exo_slamboots", false ); // Boost slam applies additional concussion effect.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## LOW PROFILE ########
|
|
if( perkName == "specialty_class_lowprofile" ) // Grants immunity to track rounds.
|
|
{
|
|
self givePerk( "specialty_radarimmune", false ); // Immune to UAV while moving.
|
|
self givePerk( "specialty_exoping_immune", false ); // Immune to Exo Ping.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## FLAK JACKET ########
|
|
if( perkName == "specialty_class_flakjacket" )
|
|
{
|
|
self givePerk( "specialty_hard_shell", false ); // No slowdown after taking explosive damage.
|
|
self givePerk( "specialty_throwback", false ); // Reset frag grenade fuse on throwback.
|
|
self givePerk( "_specialty_blastshield", false ); // Take less explosive damage.
|
|
|
|
self.specialty_blastshield_bonus = getIntProperty( "perk_blastShieldScale", 45 ) / 100;
|
|
|
|
if( IsDefined( level.hardcoreMode ) && level.hardcoreMode )
|
|
self.specialty_blastshield_bonus = getIntProperty( "perk_blastShieldScale_HC", 90 ) / 100;
|
|
|
|
return;
|
|
}
|
|
|
|
//######## LIGHTWEIGHT ########
|
|
if( perkName == "specialty_class_lightweight" )
|
|
{
|
|
self givePerk( "specialty_lightweight", false ); // Increases movement speed.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## DANGER CLOSE ########
|
|
if( perkName == "specialty_class_dangerclose" )
|
|
{
|
|
self givePerk( "specialty_explosivedamage", false ); // Do extra explosive damage. Canceled by _specialty_blastshield.
|
|
|
|
return;
|
|
}
|
|
|
|
//============================================
|
|
// Tier 2 Perks
|
|
//============================================
|
|
|
|
//######## BLIND EYE ########
|
|
if( perkName == "specialty_class_blindeye" )
|
|
{
|
|
self givePerk( "specialty_blindeye", false ); // Untargetable to Tracking Drones, Explosive Drones, AI-controlled scorestreaks (e.g. warbird).
|
|
self givePerk( "specialty_plainsight", false); // Immune to FOF overlay of Player-controlled score streaks
|
|
|
|
return;
|
|
}
|
|
|
|
//######## COLDBLOODED ########
|
|
if( perkName == "specialty_class_coldblooded" )
|
|
{
|
|
self givePerk( "specialty_coldblooded", false ); // Immune to Thermal, target enhancer, paint grenade, battlechatter
|
|
self givePerk( "specialty_spygame", false); // Crosshair doesn't appear red to enemies (and your name doesn't draw overhead )
|
|
self givePerk( "specialty_heartbreaker", false ); // Immune to hearbeat sensor. Name doesn't draw overhead (see autospot in code)?
|
|
|
|
return;
|
|
}
|
|
|
|
//######## PERIPHERALS ########
|
|
if( perkName == "specialty_class_peripherals" )
|
|
{
|
|
self givePerk( "specialty_moreminimap", false ); // Increases minimap coverage.
|
|
self givePerk( "specialty_silentkill", false ); // Your kills do not show death icons to enemy players.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## FAST HANDS ########
|
|
if( perkName == "specialty_class_fasthands" )
|
|
{
|
|
self givePerk( "specialty_quickswap", false ); // Swap weapons faster.
|
|
self givePerk( "specialty_fastoffhand", false ); // Use equipment faster.
|
|
self givePerk( "specialty_sprintreload", false ); // Enables reloading while sprinting.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## GUNG-HO ########
|
|
if( perkName == "specialty_class_dexterity" )
|
|
{
|
|
//self givePerk( "specialty_fastsprintrecovery", false ); // Increases weapon readiness for hip-fire after sprinting. This doesn't help the player at all when paired with sprintfire.
|
|
self givePerk( "specialty_sprintfire", false ); // Enables firing while sprinting and sliding.
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
//============================================
|
|
// Tier 3 Perks
|
|
//============================================
|
|
|
|
//######## HARD WIRED ########
|
|
if( perkName == "specialty_class_hardwired" )
|
|
{
|
|
self givePerk( "specialty_empimmune", false ); // Immune to EMP grenades and the EMP Scorestreak. Code: immune to portable radar and jammer.
|
|
self givePerk( "specialty_stun_resistance", false ); // Immune to missile strike gas (nano swarm). Immune to stun grenade (see setStunResistance()).
|
|
self.stunScaler = 0.1;
|
|
|
|
return;
|
|
}
|
|
|
|
//######## TOUGHNESS ########
|
|
if( perkName == "specialty_class_toughness" )
|
|
{
|
|
self setViewKickScale( 0.2 ); // Reducing view kick when shot.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## SCAVENGER ########
|
|
if( perkName == "specialty_class_scavenger" )
|
|
{
|
|
self.ammopickup_scalar = 0.2;
|
|
self givePerk( "specialty_scavenger", false ); // Enables scavenger pack drops in code. Must be given for any of the resupply perks to work.
|
|
self givePerk( "specialty_bulletresupply", false ); // Resupplies bullet weapons.
|
|
//self givePerk( "specialty_lethalresupply", false ); // Resupplies grenades (tactical and lethal grenades).
|
|
//self givePerk( "specialty_tacticalresupply", false ); // Resupplies Exo Abilities.
|
|
//self givePerk( "specialty_explosiveammoresupply", false ); // Resupplies rocket launchers.
|
|
self givePerk( "specialty_extraammo", false ); // Spawn with extra ammo.
|
|
|
|
return;
|
|
}
|
|
|
|
//######## HARD LINE ########
|
|
if( perkName == "specialty_class_hardline" )
|
|
{
|
|
self givePerk( "specialty_hardline", false ); // Decreases Scorestreak cost by 100 points.
|
|
self maps\mp\killstreaks\_killstreaks::updateStreakCount();
|
|
|
|
return;
|
|
}
|
|
|
|
//######## BLAST SUPPRESSOR #########
|
|
// Suppresses minimap ping when performing Exo movement mechanics.
|
|
} |