This commit is contained in:
2024-12-11 11:28:08 +01:00
commit 12ac62a956
444 changed files with 303964 additions and 0 deletions

View File

@ -0,0 +1,331 @@
#include common_scripts\utility;
GOAL_KILL_WITH_TRAP = 50;
GOAL_ESCAPE_IN_TIME = 90000; // 1 minute and 30 second in ms
GOAL_ESCAPE_1ST_TIME = 1;
GOAL_ESCAPE_ALL_CHALLENGE = 1;
GOAL_ESCAPE_ALL_PLAYERS = 4;
GOAL_ESCAPE_WITH_NERF_ON = 1;
GOAL_SCAVENGE_ITEM = 40;
init_player_achievement()
{
self.achievement_list = [];
if ( isDefined( level.achievement_registration_func ) )
[[level.achievement_registration_func]]();
if ( maps\mp\alien\_utility::is_true( level.include_default_achievements ) )
register_default_achievements();
}
register_default_achievements()
{
// reference goal init_func should_update_func is_goal_reached_func complete_in_casual
register_achievement( "KILL_WITH_TRAP" , GOAL_KILL_WITH_TRAP, ::default_init , ::should_update_kill_with_trap , ::equal_to_goal );
register_achievement( "ESCAPE_ALL_PLAYERS" , GOAL_ESCAPE_ALL_PLAYERS, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "ESCAPE_IN_TIME" , GOAL_ESCAPE_IN_TIME, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "ESCAPE_1ST_TIME" , GOAL_ESCAPE_1ST_TIME, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "ESCAPE_ALL_CHALLENGE" , GOAL_ESCAPE_ALL_CHALLENGE, ::default_init , ::should_update_all_challenge , ::at_least_goal );
register_achievement( "ESCAPE_WITH_NERF_ON" , GOAL_ESCAPE_WITH_NERF_ON, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "REACH_CITY" , 1, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "REACH_CABIN" , 1, ::default_init , ::default_should_update , ::at_least_goal );
register_achievement( "SCAVENGE_ITEM" , GOAL_SCAVENGE_ITEM, ::default_init , ::default_should_update , ::equal_to_goal );
}
register_achievement( reference, goal, init_func, should_update_func, is_goal_reached_func, complete_in_casual )
{
achievement = spawnStruct();
achievement [[init_func]]( goal, should_update_func, is_goal_reached_func, complete_in_casual );
self.achievement_list[reference] = achievement;
}
default_init( goal, should_update_func, is_goal_reached_func, complete_in_casual )
{
self.progress = 0;
self.goal = goal;
self.should_update_func = should_update_func;
self.is_goal_reached_func = is_goal_reached_func;
self.achievement_completed = false;
if( isDefined( complete_in_casual ) )
self.complete_in_casual =complete_in_casual;
}
default_should_update( unused_1, unused_2, unused_3, unused_4, unused_5, unused_6, unused_7, unused_8, unused_9, unused_10 )
{
return true;
}
update_progress( progress_amount )
{
self.progress += progress_amount;
}
at_least_goal()
{
return ( self.progress >= self.goal );
}
equal_to_goal()
{
return ( self.progress == self.goal );
}
is_completed()
{
return ( self.achievement_completed );
}
can_complete_in_causal()
{
return ( maps\mp\alien\_utility::is_true( self.complete_in_casual ) );
}
mark_completed()
{
self.achievement_completed = true;
}
is_valid_achievement( achievement )
{
return ( isDefined ( achievement ) );
}
update_achievement( reference, progress_amt, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9, param_10 )
{
achievement = self.achievement_list[reference];
/#//<TODO J.C.> Move this back into release build
if(maps\mp\alien\_utility::is_chaos_mode())
return;
#/
if ( !is_valid_achievement( achievement ) )
return;
if ( achievement is_completed() )
return;
if ( maps\mp\alien\_utility::is_casual_mode() && !achievement can_complete_in_causal() )
return;
if ( achievement [[achievement.should_update_func]]( param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9, param_10 ) )
{
achievement update_progress( progress_amt );
if ( achievement [[achievement.is_goal_reached_func]]() )
{
/#
maps\mp\alien\_debug::debug_print_achievement_unlocked( reference, progress_amt );
//self IPrintLnBold( "ACHIEVEMENT: " + reference );
#/
self giveAchievement( reference );
achievement mark_completed();
}
}
}
/////////////////////////////////////////
// Related to aliens killed
/////////////////////////////////////////
update_alien_kill_achievements( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration )
{
if ( isdefined( level.update_alien_kill_achievements_func ) )
[[ level.update_alien_kill_achievements_func ]]( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration );
if ( !isDefined( eAttacker ) || !isPlayer( eAttacker ) )
return;
eAttacker update_achievement( "KILL_WITH_TRAP", 1, eInflictor );
}
should_update_kill_with_trap( eInflictor, unused_2, unused_3, unused_4, unused_5, unused_6, unused_7, unused_8, unused_9, unused_10 )
{
if ( maps\mp\alien\_utility::is_trap( eInflictor ) )
return true;
return false;
}
///////////////////////////////////////
// Related to escape
///////////////////////////////////////
update_escape_achievements( players_escaped, escape_time_remains )
{
escape_player_count = players_escaped.size;
foreach ( player in players_escaped )
{
times_escaped = player maps\mp\alien\_persistence::get_player_escaped();
num_nerf_selected = player maps\mp\alien\_prestige::get_num_nerf_selected();
player update_personal_escape_achievements( escape_player_count, escape_time_remains, times_escaped, num_nerf_selected );
}
}
update_personal_escape_achievements( escape_player_count, escape_time_remains, times_escaped, num_nerf_selected )
{
self update_achievement( "ESCAPE_ALL_PLAYERS" , escape_player_count );
self update_achievement( "ESCAPE_IN_TIME" , escape_time_remains );
self update_achievement( "ESCAPE_1ST_TIME" , times_escaped );
self update_achievement( "ESCAPE_ALL_CHALLENGE", 1 );
self update_achievement( "ESCAPE_WITH_NERF_ON" , num_nerf_selected );
}
should_update_all_challenge( unused_1, unused_2, unused_3, unused_4, unused_5, unused_6, unused_7, unused_8, unused_9, unused_10 )
{
return level.all_challenge_completed;
}
/////////////////////////////////////////
// Related to kill blocker hive
/////////////////////////////////////////
update_blocker_hive_achievements( hive_name )
{
switch( hive_name )
{
case "lodge_lung_3":
update_achievement_all_players( "REACH_CITY", 1 );
break;
case "city_lung_5":
update_achievement_all_players( "REACH_CABIN", 1 );
break;
default:
break;
}
}
update_achievement_all_players( reference, progress_amt )
{
foreach( player in level.players )
{
player update_achievement( reference, progress_amt );
}
}
/////////////////////////////////////////
// Related to scavenge item
/////////////////////////////////////////
update_scavenge_achievement()
{
self update_achievement( "SCAVENGE_ITEM", 1 );
}
/////////////////////////////////////////
// Kill alien based on weapon
/////////////////////////////////////////
update_achievement_damage_weapon( sWeapon )
{
if ( isdefined( level.update_achievement_damage_weapon_func ) )
self [[ level.update_achievement_damage_weapon_func ]] ( sWeapon );
}
// packNum is 0-indexed
eggAllFoundForPack( packNum )
{
self endon( "disconnect" );
level endon( "game_ended" );
println( "calculating eggstra xp..." );
//wait until the first hive is killed to give any awards.`
level waittill_any( "regular_hive_destroyed", "obelisk_destroyed", "outpost_encounter_completed" );
//legacy variable - if its equal to 1015 then we have already awarded xp for packNum 0.
legacyState = self GetCoopPlayerData( "alienPlayerStats", "deaths" );
eggState = self GetCoopPlayerDataReservedInt( "eggstra_state_flags" );
packEggState = ( eggState >> ( packnum * 4 ) ) & 15;
if ( packEggstate == 15 )
{
//if we got here then the player has found all the eggs for packNum.
eggstra_award_flags = self GetCoopPlayerDataReservedInt( "eggstra_award_flags" );
hasModifiedFlags = false;
//update the new flags to reflect the legacy state
//if we already awarded pack 0 xp, change eggstra_award_flags to reflect this
if ( legacyState == 1015 && (( eggstra_award_flags & ( 1 << 0 )) != 1 ))
{
//mark the xp award as already given out. This is pack 0, so or a 1 into the 0th slot of the award_flags
eggstra_award_flags |= ( 1 << 0 );
hasModifiedFlags = true;
}
// checks if we have given the xp award yet.
if (( eggstra_award_flags & ( 1 << packNum )) == 0 )
{
//if we got here we have not awarded it yet.
eggstra_award_flags |= ( 1 << packNum );
hasModifiedFlags = true;
self SetClientOmnvar( "ui_alien_eggstra_xp", true );
self thread maps\mp\alien\_persistence::wait_and_give_player_xp ( 10000, 5.0 ); //Give player 10,000 Egg-stra XP
}
//update the award flags
if ( hasModifiedFlags == true )
self SetCoopPlayerDataReservedInt( "eggstra_award_flags", eggstra_award_flags );
//needs updated to be a generic call.
self update_mp_eggs_achievement( packnum );
}
}
update_mp_eggs_achievement( dlc_num )
{
switch ( dlc_num )
{
case 0:
self update_achievement( "GOT_THEEGGSTRA_XP", 1 );
break;
case 1:
self update_achievement( "GOT_THEEGGSTRA_XP_DLC2", 1 );
break;
case 2:
self update_achievement( "GOT_THEEGGSTRA_XP_DLC3", 1 );
break;
case 3:
self update_achievement( "GOT_THEEGGSTRA_XP_DLC4", 1 );
break;
default:
break;
}
}
// Related to scavenge item
update_intel_achievement(dlc_num)
{
dlc_num = 0;
map_name = getdvar("ui_mapname" );
if(map_name == "mp_alien_armory")
dlc_num = 1;
if(map_name == "mp_alien_beacon")
dlc_num = 2;
if(map_name == "mp_alien_dlc3")
dlc_num = 3;
if(map_name == "mp_alien_last")
dlc_num = 4;
switch ( dlc_num )
{
case 1:
self update_achievement( "FOUND_ALL_INTELS", 1 );
break;
case 2:
self update_achievement( "FOUND_ALL_INTELS_MAYDAY", 1 );
break;
case 3:
self update_achievement( "AWAKENING_ALL_INTEL", 1 );
break;
case 4:
self update_achievement( "LAST_ALL_INTEL", 1 );
default:
break;
}
}

2052
maps/mp/alien/_airdrop.gsc Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
#include maps\mp\alien\_utility;
main()
{
init_fx();
}
init_fx()
{
level._effect[ "vfx_scrnfx_alien_spitter_mist" ] = LoadFX("vfx/gameplay/screen_effects/vfx_scrnfx_alien_spitter_mist");
level._effect[ "vfx_scrnfx_alien_blood" ] = LoadFX("vfx/gameplay/screen_effects/vfx_scrnfx_alien_blood" );
level._effect[ "vfx_scrnfx_tocam_slidedust_m" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_scrnfx_tocam_slidedust_m" );
level._effect[ "vfx_melee_blood_spray" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_melee_blood_spray" );
level._effect[ "vfx_blood_hit_left" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_blood_hit_left" );
level._effect[ "vfx_blood_hit_right" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_blood_hit_right" );
level._effect[ "vfx_alien_spitter_hit_left" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_alien_spitter_hit_left" );
level._effect[ "vfx_alien_spitter_hit_right" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_alien_spitter_hit_right" );
level._effect[ "vfx_alien_spitter_hit_center" ] = LoadFX( "vfx/gameplay/screen_effects/vfx_alien_spitter_hit_center" );
}
alien_fire_on()
{
if ( !isDefined( self.is_burning ) )
{
self.is_burning = 0;
}
self.is_burning++;
if ( self.is_burning == 1 )
{
self SetScriptablePartState( "body", "burning" );
//self thread disable_fire_on_death();
}
}
alien_fire_off()
{
self.is_burning--;
if ( self.is_burning > 0 )
{
return;
}
self.is_burning = undefined;
self notify( "fire_off" );
self SetScriptablePartState( "body", "normal" );
}
disable_fx_on_death()
{
self SetScriptablePartState( "body", "normal" );
}
fx_stun_damage()
{
// Minion does not have stun scriptable state
if ( self get_alien_type() == "minion" )
return;
self endon ("death");
self SetScriptablePartState("body", "shocked");
wait 0.5;
if ( IsAlive(self) )
self SetScriptablePartState("body", "normal");
}
alien_cloak_fx_on()
{
if ( !isDefined( self.is_cloaking ) )
self.is_cloaking = 0;
self playsound( "alien_teleport" );
self.is_cloaking++;
if ( self.is_cloaking == 1 )
self SetScriptablePartState( "body", "normal" );
}
alien_cloak_fx_off()
{
self.is_cloaking--;
if ( self.is_cloaking > 0 )
return;
self playsound( "alien_teleport_appear" );
self.is_cloaking = undefined;
self SetScriptablePartState( "body", "normal" );
}

View File

@ -0,0 +1,406 @@
MAX_NUM_ALIEN_HIVES = 25; // match the value defined as "MaxNumAliensHives" in matchdata.def
MAX_NUM_PERKS_BOUGHT = 50; // match the value defined as "MaxNumAliensPerksBought" in matchdata.def
MAX_NUM_UPGRADES = 32; // match the value defined as "MaxNumAliensUpgrades" in matchdata.def
CONST_MAX_BYTE = 127;
CONST_MAX_SHORT = 32767;
CONST_MAX_INT = 2147483647;
start_game_type()
{
init();
set_is_private_match();
override_gametype();
register_upgrade_types();
level thread wait_set_initial_player_count();
}
set_is_private_match()
{
setMatchData( "aliensIsPrivateMatch", getDvarInt( "xblive_privatematch" ) );
}
override_gametype() // We are overriding the matchdata "gametype" which is set from the MP logic at line 15 and 19 in _matchdata.gsc
{
setMatchData( "gametype", get_alien_game_type() );
}
get_alien_game_type()
{
CONST_CHAOS_MODE = "aliens ch";
CONST_HARDCORE_MODE = "aliens hc";
CONST_CASUAL_MODE = "aliens ca";
CONST_NORMAL_MODE = "aliens";
if ( maps\mp\alien\_utility::is_chaos_mode() )
return CONST_CHAOS_MODE;
if ( maps\mp\alien\_utility::is_hardcore_mode() )
return CONST_HARDCORE_MODE;
else if ( maps\mp\alien\_utility::is_casual_mode() )
return CONST_CASUAL_MODE;
else
return CONST_NORMAL_MODE;
}
init()
{
alien_matchData = spawnStruct();
single_value_stats = [];
single_value_stats["aliensTotalDrillDamage"] = get_single_value_struct( 0, "short" );
alien_matchData.single_value_stats = single_value_stats;
challenge_results = [];
alien_matchData.challenge_results = challenge_results;
level.alien_matchData = alien_matchData;
}
wait_set_initial_player_count()
{
level endon( "gameEnded" );
level waittill("prematch_over");
setMatchData( "aliensInitialPlayerCount", validate_byte( level.players.size ) );
}
on_player_connect()
{
player_init();
set_max_player_count();
set_split_screen();
set_alien_loadout();
set_join_in_progress();
set_relics_selected();
set_upgrades_purchased();
set_upgrades_enabled();
}
player_init()
{
alien_matchData = spawnStruct();
single_value_stats = [];
single_value_stats["aliensCashSpentOnWeapon"] = get_single_value_struct( 0, "int" );
single_value_stats["aliensCashSpentOnAbility"] = get_single_value_struct( 0, "int" );
single_value_stats["aliensCashSpentOnTrap"] = get_single_value_struct( 0, "int" );
alien_matchData.single_value_stats = single_value_stats;
perk_upgraded = [];
alien_matchData.perk_upgraded = perk_upgraded;
lastStand_record = [];
lastStand_record["aliensTimesDowned"] = [];
lastStand_record["aliensTimesRevived"] = [];
lastStand_record["aliensTimesBledOut"] = [];
alien_matchData.lastStand_record = lastStand_record;
self.alien_matchData = alien_matchData;
}
set_max_player_count()
{
if ( !isDefined( level.max_player_count ) )
level.max_player_count = 0;
if ( ( level.players.size + 1 ) > level.max_player_count )
{
level.max_player_count++;
setMatchData( "aliensMaxPlayerCount", validate_byte( level.max_player_count ) );
}
}
set_split_screen()
{
setMatchData( "players", self.clientid, "isSplitscreen", self isSplitscreenPlayer() );
}
set_join_in_progress()
{
if ( prematch_over() )
setMatchData( "players", self.clientid, "aliensJIP", true );
}
prematch_over()
{
if ( isDefined( level.startTime ) ) // level.startTime is defined after the prematch period is done
return true;
return false;
}
set_alien_loadout()
{
setMatchData( "players", self.clientid, "aliensLoadOut", 0, maps\mp\alien\_persistence::get_selected_perk_0() );
setMatchData( "players", self.clientid, "aliensLoadOut", 1, maps\mp\alien\_persistence::get_selected_perk_1() );
setMatchData( "players", self.clientid, "aliensLoadOut", 2, maps\mp\alien\_persistence::get_selected_dpad_up() );
setMatchData( "players", self.clientid, "aliensLoadOut", 3, maps\mp\alien\_persistence::get_selected_dpad_down() );
setMatchData( "players", self.clientid, "aliensLoadOut", 4, maps\mp\alien\_persistence::get_selected_dpad_left() );
setMatchData( "players", self.clientid, "aliensLoadOut", 5, maps\mp\alien\_persistence::get_selected_dpad_right() );
}
set_relics_selected()
{
num_enabled_nerfs = 0;
foreach( nerf in level.nerf_list )
{
if ( self alienscheckisrelicenabled( nerf ) )
{
setMatchData( "players", self.clientid, "aliensRelics", num_enabled_nerfs, nerf );
num_enabled_nerfs++;
}
}
for( i = num_enabled_nerfs; i < level.nerf_list.size; i++ )
setMatchData( "players", self.clientid, "aliensRelics", i, "none" );
}
set_upgrades_purchased()
{
num_upgrade_purchased = 0;
foreach( upgrade_ref in level.alien_upgrades )
{
if( self maps\mp\alien\_persistence::is_upgrade_purchased( upgrade_ref ) )
{
setMatchData( "players", self.clientid, "aliensUpgradePurchased", num_upgrade_purchased, upgrade_ref );
num_upgrade_purchased++;
}
}
for( index = num_upgrade_purchased; index < MAX_NUM_UPGRADES; index++ )
setMatchData( "players", self.clientid, "aliensUpgradePurchased", index, "none" );
}
set_upgrades_enabled()
{
num_upgrade_enabled = 0;
foreach( upgrade_ref in level.alien_upgrades )
{
if( self maps\mp\alien\_persistence::is_upgrade_enabled( upgrade_ref ) )
{
setMatchData( "players", self.clientid, "aliensUpgradeEnabled", num_upgrade_enabled, upgrade_ref );
num_upgrade_enabled++;
}
}
for( index = num_upgrade_enabled; index < MAX_NUM_UPGRADES; index++ )
setMatchData( "players", self.clientid, "aliensUpgradeEnabled", index, "none" );
}
inc_drill_heli_damages( damage_amt )
{
level.alien_matchData.single_value_stats["aliensTotalDrillDamage"].value += damage_amt;
}
set_escape_time_remaining( escape_time_remains )
{
setMatchData( "aliensEscapeTimeRemaining" , validate_int( escape_time_remains ) );
}
update_challenges_status( challenge_name, result )
{
if ( level.alien_matchData.challenge_results.size > MAX_NUM_ALIEN_HIVES )
return;
challenge_status = spawnStruct();
challenge_status.challenge_name = challenge_name;
challenge_status.result = result;
level.alien_matchData.challenge_results[level.alien_matchData.challenge_results.size] = challenge_status;
}
record_perk_upgrade( perk_name )
{
if ( self.alien_matchData.perk_upgraded.size > MAX_NUM_PERKS_BOUGHT )
return;
self.alien_matchData.perk_upgraded[self.alien_matchData.perk_upgraded.size] = perk_name;
}
inc_downed_counts()
{
inc_lastStand_record( "aliensTimesDowned" );
}
inc_revived_counts()
{
inc_lastStand_record( "aliensTimesRevived" );
}
inc_bleedout_counts()
{
inc_lastStand_record( "aliensTimesBledOut" );
}
inc_lastStand_record( field_name )
{
if ( !isDefined( self.alien_matchData.lastStand_record[field_name][level.num_hive_destroyed] ) )
self.alien_matchData.lastStand_record[field_name][level.num_hive_destroyed] = 0;
self.alien_matchData.lastStand_record[field_name][level.num_hive_destroyed]++;
}
update_spending_type( amount_spent, spending_type )
{
switch( spending_type )
{
case "weapon":
self.alien_matchData.single_value_stats["aliensCashSpentOnWeapon"].value += amount_spent;
break;
case "ability":
self.alien_matchData.single_value_stats["aliensCashSpentOnAbility"].value += amount_spent;
break;
case "trap":
self.alien_matchData.single_value_stats["aliensCashSpentOnTrap"].value += amount_spent;
break;
default:
AssertMsg( "Spending type: " + spending_type + " is not recognized." );
break;
}
}
EndGame( end_condition, play_time )
{
set_game_data( end_condition, play_time );
foreach( player in level.players )
player set_player_game_data();
sendMatchData();
}
set_game_data( end_condition, play_time )
{
CONST_CHALLENGES_COMPLETED = "aliensChallengesCompleted";
setMatchData( "aliensFinalPlayerCount" , validate_byte( level.players.size ) );
setMatchData( "aliensHivesDestroyed" , validate_byte( level.num_hive_destroyed ) );
setMatchData( "aliensGameOverCondition", end_condition );
setMatchData( "aliensTotalTimeElapsed" , validate_int( play_time ) );
alien_matchData = level.alien_matchData;
foreach( matchData_field, value_struct in alien_matchData.single_value_stats )
{
value = validate_value( value_struct.value, value_struct.value_type );
setMatchData( matchData_field , value );
}
foreach( index, challenge_status in alien_matchData.challenge_results )
{
setMatchData( CONST_CHALLENGES_COMPLETED, index, "challengeId", challenge_status.challenge_name );
setMatchData( CONST_CHALLENGES_COMPLETED, index, "success" , challenge_status.result );
}
}
set_player_game_data()
{
copy_from_playerData();
set_perk_upgraded();
set_lastStand_stats();
set_single_value_stats();
}
copy_from_playerData()
{
// Those fields are already tracked in the alienSession section in player data
setMatchData( "players", self.clientid, "aliensFinalScore" , validate_int( self GetCoopPlayerData( "alienSession", "score" ) ) );
setMatchData( "players", self.clientid, "aliensDrillRepairs", validate_byte( self GetCoopPlayerData( "alienSession", "repairs" ) ) );
setMatchData( "players", self.clientid, "aliensXpEarned" , validate_int( self GetCoopPlayerData( "alienSession", "experience" ) ) );
}
set_perk_upgraded()
{
foreach( index, perk_name in self.alien_matchData.perk_upgraded )
setMatchData( "players", self.clientid, "aliensPerksBought", index, perk_name );
}
set_lastStand_stats()
{
foreach( stat_type, info_array in self.alien_matchData.lastStand_record )
{
foreach( hive_index, counts in info_array )
setMatchData( "players", self.clientid, stat_type, hive_index, validate_byte( counts ) );
}
}
set_single_value_stats()
{
foreach( field_name, value_struct in self.alien_matchData.single_value_stats )
{
value = validate_value( value_struct.value, value_struct.value_type );
setMatchData( "players", self.clientid, field_name, value );
}
}
validate_value( value, data_type )
{
switch( data_type )
{
case "byte":
return validate_byte( value );
case "short":
return validate_short( value );
case "int":
return validate_int( value );
default:
AssertMsg( "Value type: " + data_type + " is not supported" );
}
}
validate_byte( value )
{
return int( min( value, CONST_MAX_BYTE ) );
}
validate_short( value )
{
return int( min( value, CONST_MAX_SHORT ) );
}
validate_int( value )
{
return int( min( value, CONST_MAX_INT ) );
}
get_single_value_struct( initial_value, value_type )
{
value_struct = spawnStruct();
value_struct.value = initial_value;
value_struct.value_type = value_type;
return value_struct;
}
register_upgrade_types()
{
UPGRADE_TABLE = "mp/alien/alien_purchasable_items.csv";
TABLE_INDEX_COLUMN = 0;
UPGRADE_REF_COLUMN = 1;
upgrades = [];
for ( index = 0; index < MAX_NUM_UPGRADES; index++ )
{
upgrade_ref = tablelookup( UPGRADE_TABLE, TABLE_INDEX_COLUMN, index, UPGRADE_REF_COLUMN );
if ( maps\mp\agents\alien\_alien_agents::is_empty_string( upgrade_ref ) )
break;
upgrades[upgrades.size] = upgrade_ref;
}
level.alien_upgrades = upgrades;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,407 @@
#include common_scripts\utility;
#include maps\mp\gametypes\_hud_util;
#include maps\mp\_utility;
#include maps\mp\alien\_utility;
#include maps\mp\alien\_challenge_function;
init_challenge()
{
//set up the challenge table automatically
map_name = getdvar("ui_mapname" );
level.alien_challenge_table = "mp/alien/" + map_name + "_challenges.csv";
if ( maps\mp\alien\_utility::is_hardcore_mode() )
{
level.alien_challenge_table = "mp/alien/" + map_name + "_hardcore_challenges.csv";
if ( !TableExists( level.alien_challenge_table ) )
level.alien_challenge_table = "mp/alien/" + map_name + "_challenges.csv";
}
init_challenge_type();
}
spawn_challenge()
{
if ( !alien_mode_has( "challenge" ) )
return;
level.current_challenge_index = undefined;
level thread spawn_challenge_internal();
}
spawn_challenge_internal()
{
challenge = get_valid_challenge();
if ( !isDefined ( challenge ) )
{
println( "***CHALLENGE_ERROR*** - no challenge found" );
return;
}
/#
if ( GetDvar( "scr_setactivechallenge" ) != "" )
{
challenge = GetDvar( "scr_setactivechallenge" );
SetDvar( "scr_setactivechallenge" ,"" );
}
#/
activate_new_challenge ( challenge );
}
update_challenge ( challenge_name, param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9 )
{
if ( !current_challenge_is ( challenge_name ) || !alien_mode_has( "challenge" ) )
return;
if ( level.pre_challenge_active )
return;
current_challenge = level.challenge_data [ level.current_challenge ];
current_challenge [[ current_challenge.updateFunc ]]( param_1, param_2, param_3, param_4, param_5, param_6, param_7, param_8, param_9 );
}
end_current_challenge()
{
if ( current_challenge_exist() && alien_mode_has( "challenge" ) )
deactivate_current_challenge();
}
remove_all_challenge_cases()
{
level notify ( "remove_all_challenge_case" );
}
get_valid_challenge()
{
valid_challenges = [];
foreach ( challenge in level.challenge_data )
{
if ( isDefined ( challenge.already_issued ) ) //don't repeat the challenges
continue;
if ( level.players.size == 1 && !is_true(challenge.allowedinsolo) ) //challenge not allowed in solo
continue;
if ( !isDefined ( challenge.allowed_cycles ) )
continue;
allowed_cycles = strTok( challenge.allowed_cycles, " " );
foreach ( cycle in allowed_cycles ) //see if this challenge is allowed
{
if ( level.cycle_count - 1 == int( cycle ) )
{
current_hive = maps\mp\alien\_spawn_director::get_current_encounter();
if ( !isDefined ( current_hive ) )
{
println("***CHALLENGE ERROR*** - no current hive found" );
continue;
}
if ( should_skip_challenge( challenge ) )
continue;
allowed_hives = StrTok( challenge.allowed_hives," " );
foreach ( hive in allowed_hives ) //see if this challenge is allowed for this hive
{
if ( hive == current_hive )
{
valid_challenges[ valid_challenges.size ] = challenge;
break;
}
}
break;
}
}
}
if ( valid_challenges.size > 0 )
{
valid_challenge = valid_challenges[randomint( valid_challenges.size )];
valid_challenge.already_issued = true;
return valid_challenge.ref;
}
return undefined;
}
should_skip_challenge( challenge )
{
is_weapon_challenge = (challenge.ref == "ar_only" ||
challenge.ref == "smg_only" ||
challenge.ref == "lmgs_only" ||
challenge.ref == "shotguns_only" ||
challenge.ref == "2_weapons_only" ||
challenge.ref == "semi_autos_only" ||
challenge.ref == "new_weapon" ||
challenge.ref == "snipers_only" );
if( !is_weapon_challenge )
return false;
num_pistol_prestige_players = 0;
foreach ( player in level.players )
{
if ( player maps\mp\alien\_prestige::prestige_getPistolsOnly() == 1 )
num_pistol_prestige_players++;
}
if ( challenge.ref == "new_weapon" && num_pistol_prestige_players > 0 ) //skip this challenge if any single person has the nerf
return true;
if ( num_pistol_prestige_players >= level.players.size - 1 ) //skip this challenge if the majority of the players have the nerf
return true;
else
return false;
}
deactivate_current_challenge()
{
if ( !current_challenge_exist() )
return;
current_challenge = level.challenge_data [ level.current_challenge ];
unset_current_challenge();
if ( current_challenge [[ current_challenge.isSuccessFunc ]]() )
{
display_challenge_message ( "challenge_success",false );
current_challenge [[ current_challenge.rewardFunc ]]();
maps\mp\alien\_gamescore::update_players_encounter_performance( maps\mp\alien\_gamescore::get_challenge_score_component_name(), "challenge_complete" );
maps\mp\alien\_persistence::update_LB_alienSession_challenge( true );
maps\mp\alien\_alien_matchdata::update_challenges_status( current_challenge.ref, true );
level.num_challenge_completed++;
if ( !is_casual_mode() )
{
if ( level.num_challenge_completed == 10 )
{
foreach( player in level.players )
player maps\mp\alien\_persistence::give_player_tokens( 2, true );
}
}
}
else
{
display_challenge_message ( "challenge_failed",false );
current_challenge [[ current_challenge.failFunc ]]();
level.all_challenge_completed = false;
maps\mp\alien\_persistence::update_LB_alienSession_challenge( false );
maps\mp\alien\_alien_matchdata::update_challenges_status( current_challenge.ref, false );
}
current_challenge [[ current_challenge.deactivateFunc ]]();
}
activate_new_challenge ( challenge_name )
{
assert( IsDefined( challenge_name ) && isDefined ( level.challenge_data [ challenge_name ] ) );
new_challenge = level.challenge_data [ challenge_name ];
if ( new_challenge [[ new_challenge.canActivateFunc ]]() )
{
scalar = get_challenge_scalar( challenge_name );
if ( isDefined ( scalar ) )
{
level.challenge_data[ challenge_name ].goal = scalar;
level.current_challenge_scalar = scalar;
}
else
level.current_challenge_scalar = -1;
display_challenge_message ( challenge_name, true, scalar ); //get_challenge_activate_string( new_challenge ) );
set_current_challenge ( challenge_name );
level.pre_challenge_active = true;
challenge_countdown();
level.pre_challenge_active = false;
foreach ( player in level.players )
{
player setClientOmnvar ( "ui_intel_prechallenge", 0 );
}
level.current_challenge_pre_challenge = 0;
new_challenge [[ new_challenge.activateFunc ]]();
}
else
{
new_challenge [[ new_challenge.failActivateFunc ]]();
}
}
challenge_countdown()
{
level endon( "game_ended" );
new_challenge_time = int ( gettime() + 5000 );
foreach ( player in level.players )
{
player SetClientOmnvar( "ui_intel_timer",new_challenge_time );
player SetClientOmnvar ( "ui_intel_title", 1 );
}
level.current_challenge_title = 1;
wait ( 5 );
foreach ( player in level.players )
{
player SetClientOmnvar( "ui_intel_timer",-1 );
player SetClientOmnvar ( "ui_intel_title", -1 );
}
level.current_challenge_title = -1;
wait ( .5 );
}
can_pick_up_challenge ( player )
{
if ( !IsPlayer(player) )
return false;
if ( isAI( player ) )
return false;
if ( !isAlive( player ) || ( isDefined( player.fauxDead ) && player.fauxDead ) ) //there is a time when you kill your self with remote that this will pass
return false;
return true;
}
display_challenge_message ( message, activate , scalar )
{
index = TableLookup(level.alien_challenge_table, 1, message, 0 );
foreach ( player in level.players )
{
if ( activate )
{
if ( isDefined ( scalar ) )
{
player SetClientOmnvar( "ui_intel_challenge_scalar", scalar );
}
else
{
player SetClientOmnvar( "ui_intel_challenge_scalar",-1 );
}
player setClientOmnvar ( "ui_intel_prechallenge", 1 );
player SetClientOmnvar( "ui_intel_active_index", int( index ) );
level.current_challenge_index = int( index );
level.current_challenge_pre_challenge = 1;
player PlayLocalSound( "mp_intel_received" );
}
else
{
player SetClientOmnvar( "ui_intel_active_index", -1 );
player SetClientOmnvar ( "ui_intel_progress_current",-1 );
player setClientOmnvar ( "ui_intel_progress_max",-1 );
player setClientOmnvar ( "ui_intel_percent",-1 );
player SetClientOmnvar ( "ui_intel_target_player" , -1 );
player setClientOmnvar ( "ui_intel_prechallenge", 0 );
player SetClientOmnvar( "ui_intel_timer",-1 );
player SetClientOmnvar( "ui_intel_challenge_scalar" ,-1);
level.current_challenge_index = -1;
level.current_challenge_progress_max = -1;
level.current_challenge_progress_current = -1;
level.current_challenge_percent = -1;
level.current_challenge_target_player = -1;
level.current_challenge_timer = -1;
level.current_challenge_scalar = -1;
level.current_challenge_pre_challenge = 0;
}
}
if ( activate )
return;
level thread show_challenge_outcome( message, index );
}
show_challenge_outcome( message, challenge_message_index )
{
level endon("game_ended");
wait ( 1 );
foreach ( player in level.players )
{
if ( message == "challenge_failed" )
{
player SetClientOmnvar("ui_intel_active_index", int( challenge_message_index ) );
player PlayLocalSound( "mp_intel_fail" );
}
else
{
player SetClientOmnvar("ui_intel_active_index", int ( challenge_message_index ) );
player PlayLocalSound( "mp_intel_success" );
}
}
wait ( 4 );
foreach ( player in level.players )
{
player SetClientOmnvar("ui_intel_active_index",-1 );
}
}
current_challenge_exist() { return isDefined ( level.current_challenge ); }
current_challenge_is ( challenge_name ) { return ( current_challenge_exist() && level.current_challenge == challenge_name ); }
unset_current_challenge() { level.current_challenge = undefined; }
set_current_challenge ( challenge_name ) { level.current_challenge = challenge_name; }
handle_challenge_hotjoin()
{
self endon( "disconnect" );
self setClientOmnvar ( "ui_intel_prechallenge", level.current_challenge_pre_challenge );
if ( current_challenge_exist() )
{
self SetClientOmnvar( "ui_intel_active_index", int( level.current_challenge_index ) );
self SetClientOmnvar ( "ui_intel_progress_current", int ( level.current_challenge_progress_current ) );
self setClientOmnvar ( "ui_intel_progress_max", int ( level.current_challenge_progress_max ) );
self setClientOmnvar ( "ui_intel_percent", int ( level.current_challenge_percent ) );
self SetClientOmnvar ( "ui_intel_target_player" , int ( level.current_challenge_target_player ) );
self setclientOmnvar ( "ui_intel_title", int ( level.current_challenge_title ) );
if ( level.current_challenge_timer > 0 )
self SetClientOmnvar( "ui_intel_timer", int ( gettime() + ( level.current_challenge_timer * 1000) ) );
self SetClientOmnvar( "ui_intel_challenge_scalar", level.current_challenge_scalar );
}
if ( level.current_challenge == "50_percent_accuracy" || level.current_challenge == "75_percent_accuracy" )// accuracy challenges
{
challenge = level.challenge_data[ level.current_challenge ];
self thread track_percent_accuracy_shots_fired_internal( challenge );
}
else if ( level.current_challenge == "no_reloads" ) //no reloads
{
self thread wait_for_reload();
}
else if ( level.current_challenge == "no_abilities" ) // use no abilities
{
self thread wait_for_ability_use();
}
if ( isDefined ( level.current_drill_health ) )
{
SetOmnvar( "ui_alien_drill_health_text", int( level.current_drill_health ) );
}
if ( isDefined ( level.current_drill_time ) )
{
SetOmnvar( "ui_alien_drill_end_milliseconds", int( level.current_drill_time ) );
}
}
get_num_challenge_completed()
{
if ( !isDefined( level.num_challenge_completed ) )
return 0;
else
return level.num_challenge_completed;
}

File diff suppressed because it is too large Load Diff

1383
maps/mp/alien/_chaos.gsc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,135 @@
#include maps\mp\alien\_laststand;
CONST_CHAOS_SELF_REVIVE_TIME = 15;
CONST_CHAOS_REVIVE_TIME = 3000; // in ms
CONST_CHAOS_INITIAL_LASTSTANDS = 3;
chaos_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity )
{
gameShouldEnd = chaos_gameShouldEnd( self );
if ( gameShouldEnd )
maps\mp\alien\_chaos_utility::chaos_end_game();
if ( is_killed_by_kill_trigger( bleedOutSpawnEntity ) )
return process_killed_by_kill_trigger( bleedOutSpawnEntity );
chaos_dropIntoLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity, gameShouldEnd );
}
process_killed_by_kill_trigger( bleedOutSpawnEntity )
{
self setOrigin( bleedOutSpawnEntity.origin );
maps\mp\alien\_death::set_kill_trigger_event_processed( self, false );
if ( !self.inLastStand )
self DoDamage( 1000, self.origin ); // Do enough damage so code will drop player into laststand.
return;
}
chaos_dropIntoLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity, gameShouldEnd )
{
self endon( "disconnect" );
level endon( "game_ended" );
self notify( "last_stand" );
enter_GamemodeSpecificAction();
enter_laststand();
if ( get_last_stand_count() > 0 )
chaos_self_revive( gameShouldEnd );
else
wait_to_be_revived( self, self.origin, undefined, undefined, true, CONST_CHAOS_REVIVE_TIME, ( 0.33, 0.75, 0.24 ), undefined, false, gameShouldEnd, true );
self notify( "revive" );
exit_laststand();
exit_GamemodeSpecificAction();
}
chaos_self_revive( gameShouldEnd )
{
self endon( "disconnect" );
self endon( "revive");
level endon( "game_ended" );
/#
if ( self maps\mp\alien\_debug::shouldSelfRevive() )
return debug_self_revive();
#/
self set_in_chaos_self_revive( self, true );
self take_lastStand( self, 1 );
self register_laststand_ammo();
return ( wait_for_chaos_self_revive( gameShouldEnd, CONST_CHAOS_SELF_REVIVE_TIME ) );
}
wait_for_chaos_self_revive( gameShouldEnd, duration )
{
if ( gameShouldEnd )
{
level waittill( "forever" ); //<NOTE J.C.> When this happens, the "game_ended" notify will already happen. Wait here is to make sure the player stays in this state until game fully ended.
return false; // Returning a false here is to be logically consistent of always returning true/false from this function
}
maps\mp\alien\_hud::set_last_stand_timer( self, duration );
self common_scripts\utility::waittill_any_timeout( duration, "revive_success" );
maps\mp\alien\_hud::clear_last_stand_timer( self );
return true;
}
chaos_gameShouldEnd( player_just_down )
{
return ( get_team_self_revive_count() == 0 && everyone_else_all_in_lastStand( player_just_down ) && no_one_else_in_chaos_self_revive( player_just_down ) );
}
no_one_else_in_chaos_self_revive( player_just_down )
{
foreach( player in level.players )
{
if ( player == player_just_down )
continue;
if ( is_in_chaos_self_revive( player ) )
return false;
}
return true;
}
get_team_self_revive_count()
{
total_self_revive_count = 0;
foreach( player in level.players )
total_self_revive_count += player get_last_stand_count();
return total_self_revive_count;
}
CONST_PRE_GAME_IS_OVER_FLAG = "chaos_pre_game_is_over";
chaos_player_init_laststand()
{
if ( common_scripts\utility::flag( CONST_PRE_GAME_IS_OVER_FLAG ) )
return;
set_last_stand_count( self, CONST_CHAOS_INITIAL_LASTSTANDS );
self thread init_selfrevive_icon( CONST_CHAOS_INITIAL_LASTSTANDS );
}
chaos_exit_GamemodeSpecificAction( player )
{
player maps\mp\alien\_damage::setBodyArmor( level.deployablebox_vest_max );
player notify( "enable_armor" );
player set_in_chaos_self_revive( self, false );
maps\mp\alien\_chaos::process_chaos_event( "refill_combo_meter" );
}
set_in_chaos_self_revive( player, value ) { player.in_chaos_self_revive = value; }
should_instant_revive( attacker ) { return ( isDefined( attacker ) && is_in_chaos_self_revive( attacker ) ); }
is_in_chaos_self_revive( player ) { return maps\mp\alien\_utility::is_true( player.in_chaos_self_revive ); }

View File

@ -0,0 +1,542 @@
init_chaos_score_components()
{
level.combo_counter = 0;
level.score_streak = 0;
level.running_score_base = 0;
level.total_score = 0;
}
calculate_total_score()
{
level.total_score = level.running_score_base + level.combo_counter * level.score_streak;
maps\mp\alien\_hud::set_total_score( level.total_score );
return level.total_score;
}
keep_running_score()
{
level.running_score_base += get_combo_counter() * get_score_streak();
}
reset_combo_counter() { level.combo_counter = 0; }
add_combo_counter( increment ) { level.combo_counter += increment ; }
add_score_streak( increment ) { level.score_streak += increment; }
get_combo_counter() { return level.combo_counter; }
get_score_streak() { return level.score_streak; }
get_total_score() { return level.total_score; }
TABLE_INDEX_COLUMN = 0;
CHAOS_EVENT_TABLE = "mp/alien/chaos_events.csv";
GSC_ID_COLUMN = 1;
LUA_EVENT_ID_COLUMN = 2;
COMBO_INC_COLUMN = 4;
SCORE_INC_COLUMN = 5;
MAX_EVENT_INDEX = 100;
register_chaos_events()
{
level.chaos_events = [];
for ( entryIndex = 1; entryIndex <= MAX_EVENT_INDEX; entryIndex++ )
{
event_ID = table_look_up( CHAOS_EVENT_TABLE, entryIndex, GSC_ID_COLUMN );
if ( maps\mp\agents\alien\_alien_agents::is_empty_string( event_ID ) )
break;
event_info = [];
event_info["LUA_event_ID"] = int( table_look_up( CHAOS_EVENT_TABLE, entryIndex, LUA_EVENT_ID_COLUMN ) );
event_info["combo_inc"] = int( table_look_up( CHAOS_EVENT_TABLE, entryIndex, COMBO_INC_COLUMN ) );
event_info["score_inc"] = int( table_look_up( CHAOS_EVENT_TABLE, entryIndex, SCORE_INC_COLUMN ) );
level.chaos_events[event_ID] = event_info;
}
}
WEAPON_START_INDEX = 1000;
WEAPON_END_INDEX = 1099;
add_chaos_weapon( world_item_list )
{
for( index = WEAPON_START_INDEX; index <= WEAPON_END_INDEX; index++ )
{
if( is_empty_value( index ) )
break;
weapon_struct = make_weapon_struct( index );
world_item_list[world_item_list.size] = weapon_struct;
}
return world_item_list;
}
make_weapon_struct( index )
{
weapon_struct = spawnStruct();
weapon_struct.script_noteworthy = get_weapon_ref( index );
weapon_struct.origin = get_weapon_origin( index );
weapon_struct.angles = get_weapon_angles( index );
return weapon_struct;
}
WEAPON_REF_COLUMN = 1;
WEAPON_ORIGIN_COLUMN = 2;
WEAPON_ANGLES_COLUMN = 3;
is_empty_value( index ) { return ( table_look_up( level.alien_cycle_table, index, WEAPON_REF_COLUMN ) == "" ); }
get_weapon_ref( index ) { return get_weapon_info( index, WEAPON_REF_COLUMN ); }
get_weapon_origin( index ) { return transform_to_coordinate( get_weapon_info( index, WEAPON_ORIGIN_COLUMN ) ); }
get_weapon_angles( index ) { return transform_to_coordinate( get_weapon_info( index, WEAPON_ANGLES_COLUMN ) ); }
get_weapon_info( index, column ) { return table_look_up( level.alien_cycle_table, index, column ); }
register_perk( perk_ref, activate_func, deactivate_func )
{
perk_info = [];
perk_info["perk_ref"] = perk_ref;
perk_info["activate_func"] = activate_func;
perk_info["deactivate_func"] = deactivate_func;
perk_info["LUA_perk_ID"] = get_LUA_perk_ID( perk_ref );
perk_info["is_activated"] = false;
level.perk_progression[get_activation_level( perk_ref )] = perk_info;
}
CHAOS_PERK_TABLE = "mp/alien/chaos_perks.csv";
ACTIVATION_LEVEL_COLUMN = 1;
LUA_PERK_ID_COLUMN = 2;
get_LUA_perk_ID( perk_ref ) { return int( table_look_up( CHAOS_PERK_TABLE, perk_ref, LUA_PERK_ID_COLUMN ) ); }
get_activation_level( perk_ref ) { return int( table_look_up( CHAOS_PERK_TABLE, perk_ref, ACTIVATION_LEVEL_COLUMN ) ); }
DROP_LOC_START_INDEX = 4000;
DROP_LOC_END_INDEX = 4099;
DROP_LOC_COLUMN = 1;
register_drop_locations()
{
level.chaos_bonus_loc = [];
level.chaos_bonus_loc_used = [];
for( index = DROP_LOC_START_INDEX; index <= DROP_LOC_END_INDEX; index++ )
{
drop_loc = table_look_up( level.alien_cycle_table, index, DROP_LOC_COLUMN );
if( maps\mp\agents\alien\_alien_agents::is_empty_string( drop_loc ) )
break;
level.chaos_bonus_loc[level.chaos_bonus_loc.size] = transform_to_coordinate( drop_loc );
}
}
PROGRESSION_START_INDEX = 5000;
PROGRESSION_END_INDEX = 5099;
WAIT_DURATION_COLUMN = 1;
NUM_OF_DROPS_COLUMN = 2;
GROUP_TYPE_COLUMN = 3;
GROUP_CHANCE_COLUMN = 4;
ITEM_CHANCE_COLUMN = 5;
register_bonus_progression()
{
level.chaos_bonus_progression = [];
max_num_of_drops = 0;
for( index = PROGRESSION_START_INDEX; index <= PROGRESSION_END_INDEX; index++ )
{
wait_duration = table_look_up( level.alien_cycle_table, index, WAIT_DURATION_COLUMN );
if( maps\mp\agents\alien\_alien_agents::is_empty_string( wait_duration ) )
break;
bonus_info = [];
bonus_info["wait_duration"] = int( wait_duration );
bonus_info["num_of_drops"] = int( table_look_up( level.alien_cycle_table, index, NUM_OF_DROPS_COLUMN ) );
bonus_info["package_group_type"] = strTok( table_look_up( level.alien_cycle_table, index, GROUP_TYPE_COLUMN ), " " );
bonus_info["package_group_chance"] = convert_array_to_int( strTok( table_look_up( level.alien_cycle_table, index, GROUP_CHANCE_COLUMN ), " " ) );
bonus_info["item_chance"] = strTok( table_look_up( level.alien_cycle_table, index, ITEM_CHANCE_COLUMN ), " " );
AssertEx( bonus_info["num_of_drops"] <= bonus_info["package_group_type"].size, "For wait duration: " + wait_duration + ", there is not enough bonus packages to support " + bonus_info["num_of_drops"] + " drops." );
if ( bonus_info["num_of_drops"] > max_num_of_drops )
max_num_of_drops = bonus_info["num_of_drops"];
level.chaos_bonus_progression[level.chaos_bonus_progression.size] = bonus_info;
}
level.chaos_max_used_loc_stored = level.chaos_bonus_loc.size - max_num_of_drops;
}
convert_array_to_int( string_array )
{
int_array = [];
foreach( string in string_array )
int_array[int_array.size] = int( string );
return int_array;
}
transform_to_coordinate( text_string )
{
tokenized = StrTok( text_string, "," );
return ( int( tokenized[0] ), int( tokenized[1] ), int( tokenized[2] ) );
}
init_chaos_deployable( boxType, iconName, onUseCallback )
{
boxConfig = SpawnStruct();
boxConfig.modelBase = "mp_weapon_alien_crate";
boxConfig.hintString = &"ALIEN_CHAOS_BONUS_PICKUP";
boxConfig.capturingString = &"ALIEN_CHAOS_BONUS_TAKING";
boxConfig.headIconOffset = 25;
boxConfig.lifeSpan = 90.0;
boxConfig.useXP = 0;
boxConfig.voDestroyed = "ballistic_vest_destroyed";
boxConfig.onUseSfx = "ammo_crate_use";
boxConfig.onUseCallback = onUseCallback;
boxConfig.canUseCallback = maps\mp\alien\_deployablebox::default_canUseDeployable;
boxConfig.useTime = 500;
boxConfig.maxHealth = 150;
boxConfig.damageFeedback = "deployable_bag";
boxConfig.maxUses = 1;
boxConfig.icon_name = iconName;
add_to_chaos_bonus_package_type( boxType );
maps\mp\alien\_deployablebox::init_deployable( boxType, boxConfig );
}
get_random_player() { return level.players[ randomint( level.players.size ) ]; }
table_look_up( table, index, target_column ) { return tableLookup( table, TABLE_INDEX_COLUMN, index, target_column ); }
get_drop_location_rated( desired_dir, base_pos )
{
MIN_DIST_SQD_FROM_ALL_PLAYER = 22500; // 150 * 150
MAX_DIST_SQD_FROM_ALL_PLAYER = 90000; // 300 * 300
DIST_FROM_ALL_PLAYER_WEIGHT = 1.0;
DESIRED_DIR_WEIGHT = 1.0;
RANDOM_WEIGHT = 2.0;
best_location_rating = -1000.0;
best_location = ( 0, 0, 0 );
foreach( location in level.chaos_bonus_loc )
{
if ( location_recently_used( location ) )
continue;
rating = 0.0;
foreach( player in level.players )
{
player_to_location_distanceSquared = DistanceSquared( player.origin, location );
if ( player_to_location_distanceSquared > MIN_DIST_SQD_FROM_ALL_PLAYER )
rating += DIST_FROM_ALL_PLAYER_WEIGHT;
if ( player_to_location_distanceSquared < MAX_DIST_SQD_FROM_ALL_PLAYER )
rating += DIST_FROM_ALL_PLAYER_WEIGHT;
}
base_pos_to_location = vectorNormalize( ( 0, vectorToYaw( location - base_pos ), 0 ) );
rating += VectorDot( base_pos_to_location, desired_dir ) * DESIRED_DIR_WEIGHT;
rating += randomFloat( RANDOM_WEIGHT );
if ( rating > best_location_rating )
{
best_location_rating = rating;
best_location = location;
}
}
register_location( best_location );
return best_location;
}
register_location( location )
{
if( level.chaos_bonus_loc_used.size == level.chaos_max_used_loc_stored )
{
for( i = 0; i < level.chaos_max_used_loc_stored - 1; i++ )
level.chaos_bonus_loc_used[i] = level.chaos_bonus_loc_used[i+1];
level.chaos_bonus_loc_used[level.chaos_max_used_loc_stored - 1] = location;
}
else
{
level.chaos_bonus_loc_used[level.chaos_bonus_loc_used.size] = location;
}
}
location_recently_used( location )
{
return common_scripts\utility::array_contains( level.chaos_bonus_loc_used, location );
}
reset_alien_kill_streak() { level.current_alien_kill_streak = 0; }
inc_alien_kill_streak() { level.current_alien_kill_streak++; }
get_alien_kill_streak() { return level.current_alien_kill_streak; }
play_FX_on_package( package_loc, owner_angles )
{
CONST_XY_OFFSET = ( -0.5, 5.6, 0 ); // To correct the fact that tag_origin is not placed at the center for the model "mp_weapon_alien_crate"
CONST_Z_OFFSET = ( 0, 0, 5 ); // To raise the FX up a little above the ground
XY_offset = RotateVector( CONST_XY_OFFSET, owner_angles );
FX_loc = package_loc + XY_offset;
FX_loc += CONST_Z_OFFSET;
fx= SpawnFX( common_scripts\utility::getfx( "chaos_pre_bonus_drop" ), FX_loc );
TriggerFx( fx );
return fx;
}
clean_up_monitor( fx, box )
{
box waittill( "death" );
fx delete();
}
init_highest_combo() { level.highest_combo = 0; }
record_highest_combo( combo_counter )
{
if ( combo_counter <= level.highest_combo )
return;
level.highest_combo = combo_counter ;
foreach ( player in level.players )
player maps\mp\alien\_persistence::LB_player_update_stat( "hits", combo_counter, true ); // In Chaos, we are using session data "hits" to record the highest combo
}
CYCLE_PARAMETER_START_INDEX = 500;
CYCLE_PARAMETER_END_INDEX = 599;
CYCLE_NUMBER_COLUMN = 1;
CYCLE_DURATION_COLUMN = 6;
register_cycle_duration()
{
level.chaos_cycle_duration = [];
for( index = CYCLE_PARAMETER_START_INDEX; index <= CYCLE_PARAMETER_END_INDEX; index++ )
{
cycle_number = table_look_up( level.alien_cycle_table, index, CYCLE_NUMBER_COLUMN );
if( maps\mp\agents\alien\_alien_agents::is_empty_string( cycle_number ) )
break;
level.chaos_cycle_duration[level.chaos_cycle_duration.size] = int( table_look_up( level.alien_cycle_table, index, CYCLE_DURATION_COLUMN ) );
}
}
SPAWN_LOC_START_INDEX = 6000;
SPAWN_LOC_END_INDEX = 6099;
SPAWN_LOC_ORIGIN_COLUMN = 1;
SPAWN_LOC_ANGLES_COLUMN = 2;
SPAWN_LOC_LINKTO_COLUMN = 3;
SPAWN_LOC_NOTEWORTHY_COLUMN = 4;
add_extra_spawn_locations()
{
extra_spawn_locations = [];
for( index = SPAWN_LOC_START_INDEX; index <= SPAWN_LOC_END_INDEX; index++ )
{
spawn_loc_origin = table_look_up( level.alien_cycle_table, index, SPAWN_LOC_ORIGIN_COLUMN );
if( maps\mp\agents\alien\_alien_agents::is_empty_string( spawn_loc_origin ) )
break;
spawn_location = spawnStruct();
spawn_location.origin = transform_to_coordinate( spawn_loc_origin );
spawn_location.angles = transform_to_coordinate( table_look_up( level.alien_cycle_table, index, SPAWN_LOC_ANGLES_COLUMN ) );
spawn_location.script_linkto = translate_to_actual_zone_name( table_look_up( level.alien_cycle_table, index, SPAWN_LOC_LINKTO_COLUMN ) );
spawn_location.script_noteworthy = table_look_up( level.alien_cycle_table, index, SPAWN_LOC_NOTEWORTHY_COLUMN );
extra_spawn_locations[extra_spawn_locations.size] = spawn_location;
}
maps\mp\alien\_spawn_director::put_spawnLocations_into_cycle_data( extra_spawn_locations, level.cycle_data );
}
DEFAULT_INIT_COMBO_DURATION = 4.0; // Time (in sec) after a combo action / event that the player has to do another action to keep the combo going
init_combo_duration()
{
if ( !isDefined( level.combo_duration ) )
level.combo_duration = DEFAULT_INIT_COMBO_DURATION;
}
get_combo_duration() { return level.combo_duration; }
adjust_combo_duration( delta ) { level.combo_duration += delta; }
COMBO_DURATION_START_INDEX = 7000;
COMBO_DURATION_END_INDEX = 7099;
COMBO_DURATION_PRE_DELTA_INTERVAL_COLUMN = 1;
COMBO_DURATION_DELTA_COLUMN = 2;
register_combo_duration_schedule()
{
level.combo_duration_schedule = [];
for( index = COMBO_DURATION_START_INDEX; index <= COMBO_DURATION_END_INDEX; index++ )
{
pre_delta_interval = table_look_up( level.alien_cycle_table, index, COMBO_DURATION_PRE_DELTA_INTERVAL_COLUMN );
if( maps\mp\agents\alien\_alien_agents::is_empty_string( pre_delta_interval ) )
break;
duration_delta = [];
duration_delta["pre_delta_interval"] = float( pre_delta_interval );
duration_delta["delta"] = float( table_look_up( level.alien_cycle_table, index, COMBO_DURATION_DELTA_COLUMN ) );
level.combo_duration_schedule[level.combo_duration_schedule.size] = duration_delta;
}
}
DEFAULT_BONUS_PACKAGE_CAP = 3;
init_bonus_package_cap()
{
if ( !isDefined( level.chaos_bonus_package_cap ) )
level.chaos_bonus_package_cap = DEFAULT_BONUS_PACKAGE_CAP;
}
get_bonus_package_cap() { return level.chaos_bonus_package_cap; }
init_chaos_bonus_package_type() { level.chaos_bonus_package_type = []; }
add_to_chaos_bonus_package_type( package_type ) { level.chaos_bonus_package_type[level.chaos_bonus_package_type.size] = package_type; }
get_current_num_bonus_package()
{
result = 0;
foreach ( package_type in level.chaos_bonus_package_type )
result += level.deployable_box[package_type].size;
return result;
}
chaos_end_game()
{
if ( chaos_should_end() )
level thread maps\mp\gametypes\aliens::AlienEndGame( "axis", maps\mp\alien\_hud::get_end_game_string_index( "kia" ) );
}
CONST_IN_HOST_MIGRATION_FLAG = "in_host_migration";
chaos_should_end()
{
/#
if ( getDvarInt( "chaos_no_fail", 0 ) == 1 )
return false;
#/
if ( common_scripts\utility::flag( CONST_IN_HOST_MIGRATION_FLAG ) )
return false;
return true;
}
/#
reset_chaos_no_fail() { setDvar( "chaos_no_fail", 0 ); }
#/
should_process_alien_killed_event( attacker )
{
return ( isPlayer( attacker ) || ( isDefined( attacker.owner ) && isPlayer( attacker.owner ) ) || ( isDefined( attacker.team ) && attacker.team == "allies" ) );
}
should_process_alien_damaged_event( sWeapon )
{
if ( isDefined( sWeapon ) && sWeapon == "alien_minion_explosion" )
return false;
return true;
}
unset_player_perks( player )
{
foreach( perk_info in level.perk_progression )
{
if ( perk_info["is_activated"] )
[[perk_info["deactivate_func"]]]( player, perk_info["perk_ref"] );
}
player PlayLocalSound( "mp_splash_screen_default" );
}
give_activated_perks( player )
{
foreach( perk_info in level.perk_progression )
{
if ( perk_info["is_activated"] )
[[perk_info["activate_func"]]]( player, perk_info["perk_ref"] );
}
}
set_all_perks_inactivated()
{
foreach( perk_info in level.perk_progression )
perk_info["is_activated"] = false;
}
get_attacker_as_player( attacker )
{
if ( isPlayer( attacker ) )
return attacker;
if ( isDefined( attacker.owner ) && isPlayer( attacker.owner ) )
return attacker.owner;
return undefined;
}
MAX_EVENT_COUNT = 18; // How many choas events are listed in the chaos_events.csv
init_event_counts()
{
level.chaos_event_counts = [];
for( i = 1; i <= MAX_EVENT_COUNT; i++ )
level.chaos_event_counts[i] = 0;
}
update_HUD_event_counts()
{
for( i = 1; i <= MAX_EVENT_COUNT; i++ )
maps\mp\alien\_hud::set_event_count( i, level.chaos_event_counts[i] );
}
inc_event_count( event_ID ) { level.chaos_event_counts[event_ID]++; }
register_pre_end_game_display_func() { level.pre_end_game_display_func = ::update_HUD_event_counts; }
translate_to_actual_zone_name( zone_name_list )
{
actual_zone_name_list = [];
zone_name_list = StrTok( zone_name_list, " " );
foreach ( zone_name in zone_name_list )
{
foreach ( actual_zone_name, spawn_data in level.cycle_data.spawn_zones )
{
if ( IsSubStr( actual_zone_name, zone_name ) )
actual_zone_name_list[actual_zone_name_list.size] = actual_zone_name;
}
}
/# AssertEx( actual_zone_name_list.size == zone_name_list.size, "Unable to find the actual zone name for some zones." ); #/
if ( actual_zone_name_list.size == 0 )
{
result_actual_name_string = "";
}
else
{
result_actual_name_string = actual_zone_name_list[0];
for( i = 1; i < actual_zone_name_list.size; i++ )
result_actual_name_string = result_actual_name_string + " " + actual_zone_name_list[i];
}
return result_actual_name_string;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1284
maps/mp/alien/_damage.gsc Normal file

File diff suppressed because it is too large Load Diff

716
maps/mp/alien/_death.gsc Normal file
View File

@ -0,0 +1,716 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
#include maps\mp\alien\_utility;
//=======================================================
// onPlayerKilled
//=======================================================
onPlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, killId)
{
if ( level.gameEnded == true )
return;
if ( kill_trigger_event_was_processed() )
return;
set_kill_trigger_event_processed( self, true );
maps\mp\alien\_laststand::Callback_PlayerLastStandAlien( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, getKillTriggerSpawnLoc() );
}
kill_trigger_event_was_processed() { return is_true( self.kill_trigger_event_processed ); }
set_kill_trigger_event_processed( player, value ) { self.kill_trigger_event_processed = value; }
//=======================================================
// onNormalDeath
//=======================================================
onNormalDeath( victim, attacker, lifeId )
{
if ( game["state"] == "postgame" && game["teamScores"][attacker.team] > game["teamScores"][level.otherTeam[attacker.team]] )
attacker.finalKill = true;
}
CONST_DANGEROUS_RADIUS = 256;
CONST_DANGEROUS_DURATION = 10;
CONST_DANGEROUS_DURATION_TRAP = 3;
CONST_KILLS_PER_TOKEN_AWARD = 300;
//=======================================================
// onAlienAgentKilled
//=======================================================
onAlienAgentKilled( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration )
{
// scene aliens suicide skips all regular alien dying logic
if ( isdefined( sMeansOfDeath ) && sMeansOfDeath == "MOD_SUICIDE" && isdefined( self.scene ) && self.scene )
return;
self.isActive = false;
self.hasDied = false;
self.owner = undefined;
type = self.alien_type;
pet_spawned = false;
if ( !isDefined ( vDir ) )
vDir = anglesToForward( self.angles );
self maps\mp\alien\_alien_fx::disable_fx_on_death();
if ( sMeansOfDeath == "MOD_TRIGGER_HURT" )
return; // died by hurt trigger
// Mark nearby nodes as dangerous - less for traps
dangerous_duration = CONST_DANGEROUS_DURATION;
if ( maps\mp\alien\_utility::is_trap( eInflictor ) )
{
dangerous_duration = CONST_DANGEROUS_DURATION_TRAP;
}
level thread maps\mp\alien\_utility::mark_dangerous_nodes( self.origin, CONST_DANGEROUS_RADIUS, dangerous_duration );
isPetTrapKill = is_pettrap_kill( eInflictor );
//if killed with a special weapon then turn the alien into a pet
if ( sWeapon == "alienthrowingknife_mp" && sMeansofDeath == "MOD_IMPACT" || isPetTrapKill || is_true( self.hypnoknifed ) )
{
if ( self maps\mp\alien\_utility::can_hypno( eAttacker, isPetTrapKill ) )
{
thread maps\mp\gametypes\aliens::spawnAllyPet( type, 1, self.origin, eAttacker, self.angles , isPetTrapKill );
pet_spawned = true;
if ( type == "elite" && isPetTrapKill && isDefined( level.update_achievement_hypno_trap_func ) )
eAttacker [[level.update_achievement_hypno_trap_func]]();
}
//don't delete the pet trap!
if ( !isPetTrapKill )
eInflictor delete();
}
should_do_custom_death = false;
if ( isDefined( level.custom_alien_death_func ) )
should_do_custom_death = self [[level.custom_alien_death_func]]( eInflictor, eAttacker,iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc );
if ( should_do_pipebomb_death( sWeapon ) )
{
self thread do_pipebomb_death();
}
else if ( self should_play_death() && sMeansOfDeath != "MOD_SUICIDE" && !pet_spawned && !should_do_custom_death )
play_death_anim_and_ragdoll( eInflictor, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc );
self on_alien_type_killed( pet_spawned );
self maps\mp\agents\alien\_alien_think::OnEnterAnimState( self.currentAnimState, "death" ); // we don't need to enter death so much as exit currentAnimState.
//notify for dlc vo
eAttacker notify("dlc_vo_notify", get_alien_type() + "_killed", eAttacker);
switch ( get_alien_type() )
{
case "mammoth":
self PlaySoundOnMovingEnt( "queen_death" );
break;
case "elite":
self PlaySoundOnMovingEnt( "queen_death" );
break;
case "minion":
self PlaySoundOnMovingEnt( "alien_minion_explode" );
break;
case "spitter":
self PlaySoundOnMovingEnt( "spitter_death" );
break;
default:
self PlaySoundOnMovingEnt( "alien_death" );
break;
}
// chopper reward
if ( isdefined( level.attack_heli ) && eAttacker == level.attack_heli )
{
reward_point = self maps\mp\alien\_gamescore::get_reward_point_for_kill();
assertex( isdefined( eAttacker.reward_pool ) );
reward_unit = reward_point / eAttacker.reward_pool.size;
// reset
foreach ( player in eAttacker.reward_pool )
{
if ( isdefined( player ) )
player.chopper_reward = 0;
}
// add
foreach ( player in eAttacker.reward_pool )
{
if ( isdefined( player ) )
player.chopper_reward += reward_unit;
}
// give
foreach ( player in level.players )
{
if ( isdefined( player ) && isdefined( player.chopper_reward ) )
maps\mp\alien\_gamescore::giveKillReward( player, int( player.chopper_reward ), "large" );
}
}
else
{
if ( Isdefined( eAttacker.pet ) && ( eAttacker.pet == 1 ) )
{
maps\mp\alien\_gamescore::give_attacker_kill_rewards( eAttacker.owner );
}
else
{
maps\mp\alien\_gamescore::give_attacker_kill_rewards( eAttacker, sHitLoc );
}
// weaponstats tracking: register weapon shot hit
eAttacker thread maps\mp\alien\_persistence::update_weaponstats_kills( sWeapon, 1 );
}
//update any challenges related to aliens being killed
maps\mp\alien\_challenge_function::update_alien_death_challenges( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration );
//update any achievements related to aliens being killed
maps\mp\alien\_achievement::update_alien_kill_achievements( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, timeOffset, deathAnimDuration );
//update alien session stats related to aliens being killed
maps\mp\alien\_persistence::update_alien_kill_sessionStats( eInflictor, eAttacker );
if ( is_chaos_mode() )
maps\mp\alien\_chaos::update_alien_killed_event( get_alien_type(), self.origin, eAttacker );
blackBox_alienKilled( eAttacker );
attacker_as_player = get_attacker_as_player( eAttacker );
if( IsDefined( attacker_as_player ) )
{
record_player_kills( attacker_as_player );
check_award_token_for_kill( attacker_as_player );
}
level notify( "alien_killed",self.origin, sMeansOfDeath, eAttacker );
}
get_attacker_as_player( eAttacker )
{
if( IsPlayer( eAttacker ) )
return eAttacker;
if ( IsDefined( eAttacker.owner ) && IsPlayer( eAttacker.owner ) )
return eAttacker.owner;
return undefined;
}
record_player_kills( player )
{
player maps\mp\alien\_persistence::set_player_kills();
player maps\mp\alien\_persistence::eog_player_update_stat( "kills", 1 );
}
check_award_token_for_kill( player )
{
killCount = player maps\mp\alien\_persistence::get_player_kills();
if ( killCount % CONST_KILLS_PER_TOKEN_AWARD == 0 )
{
player maps\mp\alien\_persistence::give_player_tokens( 1, true );
}
}
on_alien_type_killed( pet_spawned )
{
switch ( self get_alien_type() )
{
case "minion":
level thread maps\mp\agents\alien\_alien_minion::minion_explode_on_death( self.origin );
break;
case "spitter":
maps\mp\agents\alien\_alien_spitter::spitter_death();
break;
default:
// Check for level specific overrides
if( isDefined( level.dlc_alien_death_override_func ))
self [[level.dlc_alien_death_override_func]]( pet_spawned );
break;
}
}
should_play_death()
{
switch( get_alien_type() )
{
case "minion":
case "seeder":
case "bomber":
return false;
default:
return true;
}
}
play_death_anim_and_ragdoll( eInflictor, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc )
{
ORIENTED_DEATH_OFFSET = 24;
APEX_TRAVERSAL_DEATH_OFFSET = 30;
if ( GetDvarInt( "alien_easter_egg" ) > 0 || ( isdefined( level.easter_egg_lodge_sign_active ) && level.easter_egg_lodge_sign_active ) )
{
PlayFX( level._effect[ "arcade_death" ], self.origin );
//self thread alien_toy_death();
}
else
{
primary_animState = get_primary_death_anim_state();
if ( !is_normal_upright( AnglesToUp( self.angles ) ) )
move_away_from_surface( AnglesToUp( self.angles ), ORIENTED_DEATH_OFFSET );
if ( isDefined( self.apexTraversalDeathVector ) )
move_away_from_surface( self.apexTraversalDeathVector, APEX_TRAVERSAL_DEATH_OFFSET );
play_death_anim_and_ragdoll_internal( primary_animState, eInflictor, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc );
}
}
should_do_immediate_ragdoll( deathAnimState )
{
if ( IsDefined( level.dlc_alien_should_immediate_ragdoll_on_death_override_func ) )
{
should_immediate_ragdoll = [[level.dlc_alien_should_immediate_ragdoll_on_death_override_func]]( deathAnimState );
if ( IsDefined( should_immediate_ragdoll ) )
return should_immediate_ragdoll;
}
switch ( deathAnimState )
{
case "jump":
case "traverse":
return true;
default:
return false;
}
}
play_death_anim_and_ragdoll_internal( primary_animState, eInflictor, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc )
{
if ( is_special_death( primary_animState ) )
{
animState = "special_death";
animIndex = self maps\mp\agents\alien\_alien_anim_utils::getSpecialDeathAnimIndex( primary_animState );
}
else
{
animState = self maps\mp\agents\alien\_alien_anim_utils::getDeathAnimState( ( primary_animState + "_death" ), iDamage );
animIndex = self maps\mp\agents\alien\_alien_anim_utils::getDeathAnimIndex( primary_animState , vDir, sHitLoc );
}
do_immediate_ragdoll = should_do_immediate_ragdoll( primary_animState );
self ScrAgentSetPhysicsMode( get_death_anim_physics_mode( animState ) );
self SetAnimState( animState, animIndex );
self.body = get_clone_agent( animState, animIndex );
self thread handle_ragdoll( self.body, animState, do_immediate_ragdoll );
}
move_away_from_surface( direction, offset_length )
{
offsetLocation = self.origin + direction * offset_length;
self SetOrigin( offsetLocation );
}
get_primary_death_anim_state()
{
// special death case
if ( isdefined( self.shocked ) && self.shocked ) //for electric fence, shock backwards anim
return "electric_shock_death";
switch ( self.currentAnimState )
{
case "scripted":
{
return "idle";
}
case "move":
{
if ( self.trajectoryActive )
return "jump";
else
return "run";
}
case "idle":
{
return "idle";
}
case "melee":
{
if ( self.trajectoryActive )
return "jump";
if ( self.melee_in_move_back || self.melee_in_posture )
return "idle";
else
return "run";
}
case "traverse":
{
if ( self.trajectoryActive )
return "jump";
else
return "traverse";
}
default:
{
AssertMsg( "currentAnimState: " + self.currentAnimState + " does not have a death anim mapping." );
}
}
}
is_special_death( primary_animState )
{
switch ( primary_animState )
{
case "traverse":
case "electric_shock_death":
return true;
default:
return false;
}
}
get_death_anim_physics_mode( anim_state )
{
switch ( anim_state )
{
case "electric_shock": // so alien doesn't get stuck on electric fence geo
return "noclip";
default:
return "gravity";
}
}
get_clone_agent( animState, animIndex )
{
animEntry = self GetAnimEntry( animState, animIndex );
animLength = GetAnimLength( animEntry );
if ( AnimHasNotetrack( animEntry, "start_ragdoll" ) )
{
notetracks = GetNotetrackTimes( animEntry, "start_ragdoll" );
assert( notetracks.size > 0 );
animLength *= notetracks[0];
}
deathAnimDuration = int( animLength * 1000 ); // duration in milliseconds
return ( self CloneAgent( deathAnimDuration ) );
}
handle_ragdoll( corpse, animState, do_immediate_ragdoll )
{
deathAnim = corpse getcorpseanim();
if ( !should_do_ragdoll( corpse, deathAnim ) )
return;
if ( do_immediate_ragdoll )
{
corpse startragdoll();
if ( corpse isRagdoll() ) //Immediate ragdoll succeed
return;
/#
println( "Corpse failed immediate ragdoll at " + corpse.origin );
#/
}
delayStartRagdoll( corpse, deathAnim );
if ( !isDefined( corpse ) )
return;
// electric fence shock does physics to send aliens flying
// TODO: Remove once death animation for shock_death does this
if ( animState == "shock_death" )
{
self notify( "in_ragdoll", corpse.origin );
}
}
delayStartRagdoll( corpse, deathAnim )
{
totalAnimTime = getanimlength( deathAnim );
if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
{
times = getnotetracktimes( deathAnim, "start_ragdoll" );
startFrac = times[ 0 ];
waitTime = startFrac * totalAnimTime;
}
else
{
waitTime = 0.2;
}
wait( waitTime );
if ( !isDefined( corpse ) ) // Corpse can be deleted during host migration
{
return;
}
else
{
corpse startragdoll();
if ( corpse isRagdoll() )
return;
}
/#
println( "Corpse failed first ragdoll at " + corpse.origin );
#/
// Ragdoll failed, do a final attempt
if ( waitTime < totalAnimTime )
{
wait ( totalAnimTime - waitTime );
if ( !isDefined( corpse ) ) // Corpse can be deleted during host migration
{
return;
}
else
{
corpse startragdoll();
if ( corpse isRagdoll() )
return;
}
/#
println( "Corpse failed second ragdoll at " + corpse.origin );
#/
}
// If final attempt failed, delete the corpse
if ( isDefined( corpse ) )
corpse delete();
}
should_do_ragdoll( ent, deathAnim )
{
if ( ent isRagDoll() )
return false;
if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
return false;
if ( IsDefined( level.noRagdollEnts ) && level.noRagdollEnts.size )
{
foreach( noRag in level.noRagdollEnts )
{
if ( distanceSquared( ent.origin, noRag.origin ) < 65536 ) //256^2
return false;
}
}
return true;
}
blackBox_alienKilled( eAttacker )
{
// black box data tracking
if ( isPlayer( eAttacker )
|| ( isDefined( eAttacker.pet ) && ( eAttacker.pet == 1 ) && isPlayer( eAttacker.petowner ) )
|| ( IsDefined( eAttacker.owner ) && IsPlayer( eAttacker.owner ) )
)
{
level.alienBBData[ "aliens_killed" ]++;
}
self notify( "alien_killed" );
// black box data tracking
// =========================== blackbox print [START] ===========================
// self is agent victim that died
// attacker_is_agent
attacker_is_agent = IsAgent( eAttacker );
// attacker_alive_time, attacker_agent_type, attacker_name
if ( attacker_is_agent )
{
attacker_alive_time = ( gettime() - eAttacker.birthtime ) / 1000;
attacker_agent_type = "unknown agent";
attacker_name = "none";
if ( isdefined( eAttacker.agent_type ) )
{
attacker_agent_type = eAttacker.agent_type;
if ( isdefined( eAttacker.alien_type ) )
attacker_agent_type = eAttacker.alien_type;
}
}
else
{
attacker_alive_time = 0;
attacker_name = "none";
if ( isplayer( eAttacker ) )
{
attacker_agent_type = "player";
if ( isdefined( eAttacker.name ) )
attacker_name = eAttacker.name;
}
else
{
attacker_agent_type = "nonagent";
}
}
// attacker origin
attackerx = 0.0;
attackery = 0.0;
attackerz = 0.0;
if ( isdefined( eAttacker ) && ( IsAgent( eAttacker ) || isPlayer( eAttacker ) ) )
{
attackerx = eAttacker.origin[ 0 ];
attackery = eAttacker.origin[ 1 ];
attackerz = eAttacker.origin[ 2 ];
}
victim_alive_time = 0;
if ( isdefined( self.birthtime ) )
victim_alive_time = ( gettime() - self.birthtime ) / 1000;
victim_spawn_origin = ( 0, 0, 0 );
if ( isdefined( self.spawnorigin ) )
victim_spawn_origin = self.spawnorigin;
victim_dist_from_spawn = 0;
if ( isdefined( self.spawnorigin ) )
victim_dist_from_spawn = distance( self.origin, self.spawnorigin );
victim_damage_done = 0;
if ( isdefined( self.damage_done ) )
victim_damage_done = self.damage_done;
victim_agent_type = "unknown agent";
if ( isdefined( self.agent_type ) )
{
victim_agent_type = self.agent_type;
if ( isdefined( self.alien_type ) )
victim_agent_type = self.alien_type;
}
current_enemy_population = 0;
foreach ( agent in level.agentArray )
{
if ( !IsDefined( agent.isActive ) || !agent.isActive )
continue;
if ( isdefined( agent.team ) && agent.team == "axis" )
current_enemy_population++;
}
current_player_population = 0;
if ( isdefined( level.players ) )
current_player_population = level.players.size;
/#
if ( GetDvarInt( "alien_bbprint_debug" ) > 0 )
{
IPrintLnBold( "^8bbprint: alienkilled (1/2)\n" +
" attackerisagent=" + attacker_is_agent +
" attackeralivetime=" + attacker_alive_time +
" attackeragenttype=" + attacker_agent_type +
" attackername=" + attacker_name +
" attackerx=" + eAttacker.origin[ 0 ] +
" attackery=" + eAttacker.origin[ 1 ] +
" attackerz=" + eAttacker.origin[ 2 ] +
" victimalivetime=" + victim_alive_time );
IPrintLnBold( "^8bbprint: alienkilled (2/2)\n" +
" victimspawnoriginx=" + victim_spawn_origin[ 0 ] +
" victimspawnoriginy=" + victim_spawn_origin[ 1 ] +
" victimspawnoriginz=" + victim_spawn_origin[ 2 ] +
" victimdistfromspawn=" + victim_dist_from_spawn +
" victimdamagedone=" + victim_damage_done +
" victimagenttype=" + victim_agent_type +
" currentenemypopulation=" + current_enemy_population +
" currentplayerpopulation=" + current_player_population );
}
#/
bbprint( "alienkilled",
"attackerisagent %i attackeralivetime %f attackeragenttype %s attackername %s attackerx %f attackery %f attackerz %f victimalivetime %f victimspawnoriginx %f victimspawnoriginy %f victimspawnoriginz %f victimdistfromspawn %i victimdamagedone %i victimagenttype %s currentenemypopulation %i currentplayerpopulation %i ",
attacker_is_agent,
attacker_alive_time,
attacker_agent_type,
attacker_name,
eAttacker.origin[ 0 ],
eAttacker.origin[ 1 ],
eAttacker.origin[ 2 ],
victim_alive_time,
victim_spawn_origin[ 0 ],
victim_spawn_origin[ 1 ],
victim_spawn_origin[ 2 ],
victim_dist_from_spawn,
victim_damage_done,
victim_agent_type,
current_enemy_population,
current_player_population );
// =========================== [END] blackbox print ===========================
}
KILL_TRIGGER_SPAWN_STRUCT_TARGET_NAME = "respawn_edge";
kill_trigger_spawn_init()
{
level.killTriggerSpawnLocs = getstructArray( KILL_TRIGGER_SPAWN_STRUCT_TARGET_NAME, "targetname" );
}
getKillTriggerSpawnLoc()
{
AssertEx( level.killTriggerSpawnLocs.size > 0, "Need to put script struct around kill triggers with KVP: 'targetname', '" + KILL_TRIGGER_SPAWN_STRUCT_TARGET_NAME + "'" );
return ( getClosest ( self.origin, level.killTriggerSpawnLocs ) );
}
should_do_pipebomb_death( sWeapon )
{
alientype = self get_alien_type();
//minions already explode, and the Rhino/Elite aliens shouldn't gib
if ( alientype == "minion" || alientype == "elite" || alientype == "mammoth" )
return false;
return ( isDefined( sWeapon ) && sWeapon == "iw6_aliendlc22_mp" ); //pipe bomb
}
do_pipebomb_death()
{
PlayFx( level._effect[ "alien_gib" ], self.origin + (0,0,32) );
}
is_pettrap_kill( eInflictor )
{
return ( isDefined( eInflictor ) && isDefined( eInflictor.is_pet_trap ) );
}
general_alien_custom_death( eInflictor, eAttacker,iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc )
{
is_player = IsDefined( eAttacker ) && isPlayer ( eAttacker );
if ( is_player && isDefined ( sWeapon ) && weapon_has_alien_attachment( sWeapon ) && sMeansOfDeath != "MOD_MELEE" && !is_true ( level.easter_egg_lodge_sign_active ) )
{
PlayFx( level._effect[ "alien_ark_gib" ], self.origin + (0,0,32) );
return true;
}
else
return false;
}

1168
maps/mp/alien/_debug.gsc Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,989 @@
#include maps\mp\_utility;
#include common_scripts\utility;
#include maps\mp\gametypes\_hud_util;
#include maps\mp\alien\_utility;
/*
Deployable box killstreaks: the player will be able to place a box in the world and teammates can grab items from it
this will be used on multiple killstreaks where you can place a box in the world with something in it
*/
BOX_TIMEOUT_UPDATE_INTERVAL = 1.0;
DEFAULT_USE_TIME = 3000;
BOX_DEFAULT_HEALTH = 999999; // so that boxes aren't killed in code
init()
{
if ( !IsDefined( level.boxSettings ) )
{
level.boxSettings = [];
}
}
///////////////////////////////////////////////////
// MARKER FUNCTIONS
// 2012-06-21 wallace
// Stole an updated version from _uplink.gsc. Should probably unify all these funcs eventually
//////////////////////////////////////////////////
beginDeployableViaMarker( lifeId, boxType )
{
self thread watchDeployableMarkerCancel( boxType );
self thread watchDeployableMarkerPlacement( boxType, lifeId );
while ( true )
{
result = self waittill_any_return( "deployable_canceled", "deployable_deployed", "death", "disconnect" );
return ( result == "deployable_deployed" );
}
}
tryUseDeployable( lifeId, boxType ) // self == player
{
self thread watchDeployableMarkerCancel( boxType );
self thread watchDeployableMarkerPlacement( boxType, lifeId );
while ( true )
{
result = self waittill_any_return( "deployable_canceled", "deployable_deployed", "death", "disconnect" );
return ( result == "deployable_deployed" );
}
}
watchDeployableMarkerCancel( boxType )
{
self endon( "death" );
self endon( "disconnect" );
self endon( "deployable_deployed" );
boxConfig = level.boxSettings[ boxType ];
currentWeapon = self getCurrentWeapon();
while( currentWeapon == boxConfig.weaponInfo )
{
self waittill( "weapon_change", currentWeapon );
}
self notify( "deployable_canceled" );
}
watchDeployableMarkerPlacement( boxType, lifeId )
{
self endon( "spawned_player" ); // you shouldn't do endon( "death" ) here because this thread needs to run
self endon( "disconnect" );
self endon( "deployable_canceled" );
while( true )
{
self waittill( "grenade_fire", marker, weaponName );
if( isReallyAlive(self) )
{
break;
}
else
{
marker Delete();
}
}
self notify( "deployable_deployed" );
marker.owner = self;
marker.weaponName = weaponName;
self.marker = marker;
marker PlaySoundToPlayer( level.boxSettings[ boxType ].deployedSfx, self );
marker thread markerActivate( lifeId, boxType, ::box_setActive );
}
override_box_moving_platform_death( data )
{
self notify( "death" ); // we're doing this here instead of letting the mover code just delete us so that we can run our necessary clean-up functionality (like removal of the objective marker from the minimap)
}
markerActivate( lifeId, boxType, usedCallback ) // self == marker
{
self notify( "markerActivate" );
self endon( "markerActivate" );
//self waittill( "explode", position );
self waittill( "missile_stuck" );
owner = self.owner;
position = self.origin;
if ( !isDefined( owner ) )
return;
box = createBoxForPlayer( boxType, position, owner );
// For moving platforms.
data = SpawnStruct();
data.linkParent = self GetLinkedParent();
//fixes wall hack exploit with linked items
if ( isDefined( data.linkParent ) && isDefined( data.linkParent.model ) && DeployableExclusion( data.linkParent.model ) )
{
box.origin = data.linkParent.origin;
grandParent = data.linkParent GetLinkedParent();
if ( isDefined( grandParent ) )
data.linkParent = grandParent;
else
data.linkParent = undefined;
}
data.deathOverrideCallback = ::override_box_moving_platform_death;
box thread maps\mp\_movers::handle_moving_platforms( data );
box.moving_platform = data.linkParent;
box SetOtherEnt(owner);
// ES - 2/24/14 - This waitframe is causing an issue where, when deployed on a moving platform, the "death" notification is sent instantly, but is never caught.
wait 0.05;
//self playSound( "sentry_gun_beep" );
box thread [[ usedCallback ]]();
self delete();
if( IsDefined(box) && (box touchingBadTrigger()) )
{
box notify( "death" );
}
}
DeployableExclusion( parentModel )
{
if ( parentModel == "weapon_alien_laser_drill" )
return true;
else if ( IsSubStr( parentModel, "crafting" ) )
return true;
else if ( IsSubStr( parentModel, "scorpion_body" ) )
return true;
return false;
}
isHoldingDeployableBox()
{
curWeap = self GetCurrentWeapon();
if ( IsDefined( curWeap ) )
{
foreach( deplBoxWeap in level.boxSettings )
{
if ( curWeap == deplBoxWeap.weaponInfo )
return true;
}
}
return false;
}
///////////////////////////////////////////////////
// END MARKER FUNCTIONS
//////////////////////////////////////////////////
///////////////////////////////////////////////////
// BOX HANDLER FUNCTIONS
//////////////////////////////////////////////////
get_box_icon( resourceType, dpadName, upgrade_rank )
{
return level.alien_combat_resources[ resourceType][ dpadName ].upgrades[upgrade_rank].dpad_icon;
}
get_resource_type( dpadName )
{
if( !isDefined( dpadName ) )
return undefined;
foreach ( resource_type_name, resource_type in level.alien_combat_resources )
{
if ( IsDefined( resource_type[ dpadName ] ) )
{
return resource_type_name;
}
}
return undefined;
}
createBoxForPlayer( boxType, position, owner )
{
assertEx( isDefined( owner ), "createBoxForPlayer() called without owner specified" );
boxConfig = level.boxSettings[ boxType ];
box = Spawn( "script_model", position );
box setModel( boxConfig.modelBase );
box.health = BOX_DEFAULT_HEALTH;
box.maxHealth = boxConfig.maxHealth;
box.angles = owner.angles;
box.boxType = boxType;
box.owner = owner;
box.team = owner.team;
if ( IsDefined( boxConfig.dpadName ) )
{
box.dpadName = boxConfig.dpadName;
}
if ( IsDefined( boxConfig.maxUses ) )
{
box.usesRemaining = boxConfig.maxUses;
}
player = box.owner;
resource_type = get_resource_type( box.dpadName );
if ( is_combat_resource( resource_type ) )
{
box.upgrade_rank = player maps\mp\alien\_persistence::get_upgrade_level( resource_type );
box.icon_name = get_box_icon( resource_type, box.dpadName, box.upgrade_rank );
}
else
{
AssertEx( isDefined( boxConfig.icon_name ), "For non-combat-resource box, the .icon_name must be specified in the boxConfig struct" );
box.upgrade_rank = 0;
box.icon_name = boxConfig.icon_name;
}
// black box data tracking
level.alienBBData[ "team_item_deployed" ]++;
player maps\mp\alien\_persistence::eog_player_update_stat( "deployables", 1 );
/*
ownername = "";
if ( isdefined( owner.name ) )
ownername = owner.name;
itemname = boxType;
if ( isdefined( box.dpadName ) )
itemname = box.dpadName;
/#
if ( GetDvarInt( "alien_bbprint_debug" ) > 0 )
{
IPrintLnBold( "^8bbprint: aliendeployabledeployed \n" +
" itemname=" + itemname +
" itemlevel=" + box.upgrade_rank +
" itemx,y,z=" + position +
" ownername=" + ownername );
}
#/
bbprint( "aliendeployabledeployed",
"itemname %s itemlevel %s itemx %f itemy %f itemz %f ownername %s ",
itemname,
box.upgrade_rank,
position[0],
position[1],
position[2],
ownername );
*/
box box_setInactive();
box thread box_handleOwnerDisconnect();
box addBoxToLevelArray();
return box;
}
is_combat_resource( resource_type ) { return isDefined( resource_type ); }
box_setActive( skipOwnerUse ) // self == box
{
self setCursorHint( "HINT_NOICON" );
boxConfig = level.boxSettings[ self.boxType ];
self setHintString( boxConfig.hintString );
self.inUse = false;
curObjID = maps\mp\gametypes\_gameobjects::getNextObjID();
Objective_Add( curObjID, "invisible", (0,0,0) );
Objective_Position( curObjID, self.origin );
Objective_State( curObjID, "active" );
if( isDefined( boxConfig.shaderName ) )
Objective_Icon( curObjID, boxConfig.shaderName );
self.objIdFriendly = curObjID;
// use the deployable on the owner once
if ( ( !IsDefined( skipOwnerUse ) || !skipOwnerUse ) && IsDefined( boxConfig.onuseCallback )
&& ( !IsDefined( boxconfig.canUseCallback ) || (self.owner [[ boxConfig.canUseCallback ]]() ) )
)
{
if( isReallyAlive( self.owner ) )
self.owner [[ boxConfig.onUseCallback ]]( self );
}
if ( level.teamBased )
{
Objective_Team( curObjID, self.team );
foreach ( player in level.players )
{
if ( self.team == player.team
&& (!IsDefined(boxConfig.canUseCallback) || player [[ boxConfig.canUseCallback ]](self) )
)
{
self box_SetIcon( player, boxConfig.streakName, boxConfig.headIconOffset );
}
}
}
else
{
Objective_Player( curObjID, self.owner GetEntityNumber() );
if( !IsDefined(boxConfig.canUseCallback) || self.owner [[ boxConfig.canUseCallback ]](self) )
{
self box_SetIcon( self.owner, boxConfig.streakName, boxConfig.headIconOffset );
}
}
self MakeUsable();
self.isUsable = true;
self SetCanDamage( true );
self thread box_handleDamage();
self thread box_handleDeath();
self thread box_timeOut();
self make_entity_sentient_mp( self.team, true );
if ( IsDefined( self.owner ) )
self.owner notify( "new_deployable_box", self );
if (level.teamBased)
{
foreach ( player in level.participants )
{
_box_setActiveHelper( player, self.team == player.team, boxConfig.canUseCallback );
}
}
else
{
foreach ( player in level.participants )
{
_box_setActiveHelper( player, IsDefined( self.owner ) && self.owner == player, boxConfig.canUseCallback );
}
}
if( ( !isdefined( self.air_dropped ) || !self.air_dropped ) && !isPlayingSolo() )
level thread teamPlayerCardSplash( boxConfig.splashName, self.owner, self.team );
self thread box_playerConnected();
self thread box_agentConnected();
}
_box_setActiveHelper( player, bActivate, canUseFunc )
{
if ( bActivate )
{
if ( !IsDefined( canUseFunc ) || player [[ canUseFunc ]](self) )
{
self box_enablePlayerUse( player );
}
else
{
self box_disablePlayerUse( player );
// if this player is already a juggernaut then when they die, let them use the box
self thread doubleDip( player );
}
self thread boxThink( player );
}
else
{
self box_disablePlayerUse( player );
}
}
box_playerConnected() // self == box
{
self endon( "death" );
// when new players connect they need a boxthink thread run on them
while( true )
{
level waittill( "connected", player );
self childthread box_waittill_player_spawn_and_add_box( player );
}
}
box_agentConnected() // self == box
{
self endon( "death" );
// when new agents connect they need a boxthink thread run on them
while( true )
{
level waittill( "spawned_agent_player", agent );
self box_addBoxForPlayer( agent );
}
}
box_waittill_player_spawn_and_add_box( player ) // self == box
{
player waittill( "spawned_player" );
if ( level.teamBased )
{
self box_addBoxForPlayer( player );
}
}
box_playerJoinedTeam( player ) // self == box
{
self endon( "death" );
player endon( "disconnect" );
// when new players connect they need a boxthink thread run on them
while( true )
{
player waittill( "joined_team" );
if ( level.teamBased )
{
self box_addBoxForPlayer( player );
}
}
}
box_addBoxForPlayer( player ) // self == box
{
if ( self.team == player.team )
{
self box_enablePlayerUse( player );
self thread boxThink( player );
self box_SetIcon( player, level.boxSettings[ self.boxType ].streakName, level.boxSettings[ self.boxType ].headIconOffset );
}
else
{
self box_disablePlayerUse( player );
self maps\mp\_entityheadIcons::setHeadIcon( player, "", (0,0,0) );
}
}
box_SetIcon( player, streakName, vOffset )
{
self maps\mp\_entityheadIcons::setHeadIcon( player, self.icon_name, (0, 0, vOffset), 14, 14, undefined, undefined, undefined, undefined, undefined, false );
}
box_enablePlayerUse( player ) // self == box
{
if ( IsPlayer(player) )
self EnablePlayerUse( player );
self.disabled_use_for[player GetEntityNumber()] = false;
}
box_disablePlayerUse( player ) // self == box
{
if ( IsPlayer(player) )
self DisablePlayerUse( player );
self.disabled_use_for[player GetEntityNumber()] = true;
}
box_setInactive()
{
self makeUnusable();
self.isUsable = false;
self maps\mp\_entityheadIcons::setHeadIcon( "none", "", (0,0,0) );
if ( isDefined( self.objIdFriendly ) )
_objective_delete( self.objIdFriendly );
}
box_handleDamage() // self == box
{
boxConfig = level.boxSettings[ self.boxType ];
self maps\mp\gametypes\_damage::monitorDamage(
boxConfig.maxHealth,
boxConfig.damageFeedback,
::boxModifyDamage,
::boxHandleDeathDamage,
true // isKillstreak
);
}
boxModifyDamage( attacker, weapon, type, damage )
{
modifiedDamage = damage;
if( IsExplosiveDamageMOD( type ) )
{
modifiedDamage = damage * 1.5;
}
modifiedDamage = self maps\mp\gametypes\_damage::handleMeleeDamage( weapon, type, modifiedDamage );
modifiedDamage = self maps\mp\gametypes\_damage::handleMissileDamage( weapon, type, modifiedDamage );
modifiedDamage = self maps\mp\gametypes\_damage::handleAPDamage( weapon, type, modifiedDamage, attacker );
return modifiedDamage;
}
boxHandleDeathDamage( attacker, weapon, type, damage )
{
boxConfig = level.boxSettings[ self.boxType ];
self maps\mp\gametypes\_damage::onKillstreakKilled( attacker, weapon, type, damage, boxConfig.xpPopup, boxConfig.voDestroyed );
}
box_handleDeath()
{
self waittill ( "death" );
// this handles cases of deletion
if ( !isDefined( self ) )
return;
self box_setInactive();
self removeBoxFromLevelArray();
boxConfig = level.boxSettings[ self.boxType ];
PlayFX( getfx( "deployablebox_crate_destroy" ), self.origin );
// 2013-03-08 wsh: whould probably validate all the used fields...
if ( IsDefined( boxConfig.deathDamageMax ) )
{
owner = undefined;
if ( IsDefined(self.owner) )
owner = self.owner;
// somewhat hacky:
// shift the origin of the damage because it'll collide with the box otherwise
// we could also apply the damage after we delete the item?
RadiusDamage( self.origin + (0, 0, boxConfig.headIconOffset),
boxConfig.deathDamageRadius,
boxConfig.deathDamageMax,
boxConfig.deathDamageMin,
owner,
"MOD_EXPLOSIVE",
boxConfig.deathWeaponInfo
);
}
wait( 0.1 );
self notify( "deleting" );
self delete();
}
box_handleOwnerDisconnect() // self == box
{
self endon ( "death" );
level endon ( "game_ended" );
self notify ( "box_handleOwner" );
self endon ( "box_handleOwner" );
old_owner = self.owner;
self.owner waittill( "killstreak_disowned" );
// special case for air dropped box to stay when fake owner leaves ( owner was randomly picked )
if ( isdefined( self.air_dropped ) && self.air_dropped )
{
// reassign owner to next avaliable player
foreach ( player in level.players )
{
if ( !isdefined( player ) || ( isdefined( old_owner ) && old_owner == player ) )
continue;
self.owner = player;
self thread box_handleOwnerDisconnect(); // recurse
return;
}
}
// removed if not air dropped or if no host player found (which shouldn't happen)
self notify( "death" );
}
boxThink( player )
{
self endon ( "death" );
self thread boxCaptureThink( player );
if ( !IsDefined(player.boxes) )
{
player.boxes = [];
}
player.boxes[player.boxes.size] = self;
boxConfig = level.boxSettings[ self.boxType ];
for ( ;; )
{
self waittill ( "captured", capturer );
if (capturer == player)
{
player PlayLocalSound( boxConfig.onUseSfx );
if ( IsDefined( boxConfig.onuseCallback ) )
{
player [[ boxConfig.onUseCallback ]]( self );
if ( maps\mp\alien\_utility::is_chaos_mode() )
maps\mp\alien\_chaos::update_pickup_deployable_box_event();
}
// if this is not the owner then give the owner some xp
if( IsDefined( self.owner ) && player != self.owner )
{
self.owner thread maps\mp\gametypes\_rank::xpEventPopup( boxConfig.event );
self.owner thread maps\mp\gametypes\_rank::giveRankXP( "support", boxConfig.useXP );
}
if ( IsDefined( self.usesRemaining ) )
{
self.usesRemaining--;
if ( self.usesRemaining == 0)
{
self box_leave();
break;
}
}
self maps\mp\_entityheadIcons::setHeadIcon( player, "", (0,0,0) );
self box_disablePlayerUse( player );
self thread doubleDip( player );
}
}
}
doubleDip( player ) // self == box
{
self endon( "death" );
player endon( "disconnect" );
// air dropped rewards can not be double dipped
if( isdefined( self.air_dropped ) && self.air_dropped )
return;
// once they die, let them take from the box again
player waittill( "death" );
if( level.teamBased )
{
if( self.team == player.team )
{
self box_SetIcon( player, level.boxSettings[ self.boxType ].streakName, level.boxSettings[ self.boxType ].headIconOffset );
self box_enablePlayerUse( player );
}
}
else
{
if( IsDefined( self.owner ) && self.owner == player )
{
self box_SetIcon( player, level.boxSettings[ self.boxType ].streakName, level.boxSettings[ self.boxType ].headIconOffset );
self box_enablePlayerUse( player );
}
}
}
boxCaptureThink( player ) // self == box
{
while( isDefined( self ) )
{
self waittill( "trigger", tiggerer );
if ( is_aliens() )
{
if ( [[level.boxCaptureThink_alien_func]]( tiggerer ) )
continue;
}
if ( is_chaos_mode() )
{
switch ( self.boxType )
{
case "medic_skill":
case "specialist_skill":
case "tank_skill":
case "engineer_skill":
if( is_true( tiggerer.hasChaosClassSkill ) )
{
tiggerer maps\mp\_utility::setLowerMessage( "cant_use", &"ALIEN_CHAOS_CANT_PICKUP_BONUS", 3 );
continue;
}
else if ( is_true( tiggerer.chaosClassSkillInUse ) )
{
tiggerer maps\mp\_utility::setLowerMessage( "skill_in_use", &"ALIEN_CHAOS_SKILL_IN_USE", 3 );
continue;
}
break;
case "combo_freeze":
if( is_true( tiggerer.hasComboFreeze ) )
{
tiggerer maps\mp\_utility::setLowerMessage( "cant_use", &"ALIEN_CHAOS_CANT_PICKUP_BONUS", 3 );
continue;
}
break;
default:
break;
}
}
if (tiggerer == player
&& self useHoldThink( player, level.boxSettings[ self.boxType ].useTime )
)
{
self notify( "captured", player );
}
}
}
isFriendlyToBox( box )
{
return ( level.teamBased
&& self.team == box.team );
}
box_timeOut() // self == box
{
self endon( "death" );
level endon ( "game_ended" );
if ( box_should_leave_immediately() )
{
wait 0.05;
}
else
{
lifeSpan = level.boxSettings[ self.boxType ].lifeSpan;
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( lifeSpan );
}
self box_leave();
}
box_should_leave_immediately()
{
if ( ( self.boxtype == "deployable_ammo" && self.upgrade_rank == 4 ) || ( self.boxtype == "deployable_specialammo_comb" && self.upgrade_rank == 4 ) ) // stay to regen ammo
return false;
if ( maps\mp\alien\_utility::isPlayingSolo() && ( !isdefined( self.air_dropped ) || !self.air_dropped ) )
return true;
return false;
}
box_leave()
{
// TODO: get sound for this
//if ( isDefined( self.owner ) )
// self.owner thread leaderDialogOnPlayer( "sentry_gone" );
PlayFX( getfx( "deployablebox_crate_destroy" ), self.origin );
wait( 0.05 );
self notify( "death" );
}
deleteOnOwnerDeath( owner ) // self == box.friendlyModel or box.enemyModel, owner == box
{
wait ( 0.25 );
self linkTo( owner, "tag_origin", (0,0,0), (0,0,0) );
owner waittill ( "death" );
box_leave();
}
box_ModelTeamUpdater( showForTeam ) // self == box model (enemy or friendly)
{
self endon ( "death" );
self hide();
foreach ( player in level.players )
{
if ( player.team == showForTeam )
self showToPlayer( player );
}
for ( ;; )
{
level waittill ( "joined_team" );
self hide();
foreach ( player in level.players )
{
if ( player.team == showForTeam )
self showToPlayer( player );
}
}
}
useHoldThink( player, useTime )
{
if ( IsPlayer(player) )
player playerLinkTo( self );
else
player LinkTo( self );
player playerLinkedOffsetEnable();
player.boxParams = SpawnStruct();
player.boxParams.curProgress = 0;
player.boxParams.inUse = true;
player.boxParams.useRate = 0;
if ( isDefined( useTime ) )
{
player.boxParams.useTime = useTime;
}
else
{
player.boxParams.useTime = DEFAULT_USE_TIME;
}
//player _disableWeapon();
player disable_weapon_timeout( ( useTime + 0.05 ), "deployable_weapon_management" );
if ( IsPlayer(player) )
player thread personalUseBar( self );
result = useHoldThinkLoop( player );
assert ( isDefined( result ) );
if ( isAlive( player ) )
{
//player _enableWeapon();
player enable_weapon_wrapper( "deployable_weapon_management" );
player unlink();
}
if ( !isDefined( self ) )
return false;
player.boxParams.inUse = false;
player.boxParams.curProgress = 0;
return ( result );
}
personalUseBar( object ) // self == player
{
self endon( "disconnect" );
useBar = createPrimaryProgressBar( 0, 25 );
useBarText = createPrimaryProgressBarText( 0, 25 );
useBarText setText( level.boxSettings[ object.boxType ].capturingString );
lastRate = -1;
while ( isReallyAlive( self ) && isDefined( object ) && self.boxParams.inUse && object.isUsable && !level.gameEnded )
{
if ( lastRate != self.boxParams.useRate )
{
if( self.boxParams.curProgress > self.boxParams.useTime)
self.boxParams.curProgress = self.boxParams.useTime;
useBar updateBar( self.boxParams.curProgress / self.boxParams.useTime, (1000 / self.boxParams.useTime) * self.boxParams.useRate );
if ( !self.boxParams.useRate )
{
useBar hideElem();
useBarText hideElem();
}
else
{
useBar showElem();
useBarText showElem();
}
}
lastRate = self.boxParams.useRate;
wait ( 0.05 );
}
useBar destroyElem();
useBarText destroyElem();
}
useHoldThinkLoop( player )
{
while( !level.gameEnded && isDefined( self ) && isReallyAlive( player ) && player useButtonPressed() && player.boxParams.curProgress < player.boxParams.useTime )
{
player.boxParams.curProgress += (50 * player.boxParams.useRate);
if ( isDefined( player.objectiveScaler ) )
player.boxParams.useRate = 1 * player.objectiveScaler;
else
player.boxParams.useRate = 1;
if ( player.boxParams.curProgress >= player.boxParams.useTime )
return ( isReallyAlive( player ) );
wait 0.05;
}
return false;
}
disableWhenJuggernaut() // self == box
{
level endon( "game_ended" );
self endon( "death" );
while( true )
{
level waittill( "juggernaut_equipped", player );
self maps\mp\_entityheadIcons::setHeadIcon( player, "", (0,0,0) );
self box_disablePlayerUse( player );
self thread doubleDip( player );
}
}
addBoxToLevelArray() // self == box
{
// put the newly created box in the level array for the box type
level.deployable_box[ self.boxType ][ self GetEntityNumber() ] = self;
}
removeBoxFromLevelArray() // self == box
{
level.deployable_box[ self.boxType ][ self GetEntityNumber() ] = undefined;
}
default_canUseDeployable( boxEnt ) // self == player
{
if( ( isDefined( boxEnt ) && boxEnt.owner == self || self maps\mp\alien\_prestige::prestige_getNoDeployables() == 1.0 ) && !isdefined( boxEnt.air_dropped ) )
{
return false;
}
return true;
}
default_OnUseDeployable( boxent ) //self =a player
{
self thread maps\mp\alien\_persistence::deployablebox_used_track( boxEnt );
maps\mp\alien\_utility::deployable_box_onuse_message( boxent );
}
default_tryUseDeployable( lifeId, BOX_TYPE ) // self == player
{
result = self maps\mp\alien\_combat_resources::alien_beginDeployableViaMarker( lifeId, BOX_TYPE );
if( ( !IsDefined( result ) || !result ) )
{
return false;
}
return true;
}
init_deployable( BOX_TYPE, boxconfig )
{
if ( !IsDefined( level.boxSettings ) )
{
level.boxSettings = [];
}
level.boxSettings[ BOX_TYPE ] = boxConfig;
if ( !IsDefined( level.killStreakFuncs ) )
{
level.killStreakFuncs = [];
}
//level.killStreakFuncs[ BOX_TYPE ] = ::default_tryUseDeployable;
level.deployable_box[ BOX_TYPE ] = []; // storing each created box in their own array
}

File diff suppressed because it is too large Load Diff

65
maps/mp/alien/_dev.gsc Normal file
View File

@ -0,0 +1,65 @@
/#
init()
{
SetDevDvarIfUninitialized( "debug_reflection", "0" );
level thread onPlayerConnect();
}
onPlayerConnect()
{
for(;;)
{
level waittill( "connected", player );
player thread updateReflectionProbe();
}
}
updateReflectionProbe()
{
for(;;)
{
if ( GetDvarInt( "debug_reflection" ) == 1 )
{
if ( !IsDefined( self.debug_reflectionobject ) )
{
self.debug_reflectionobject = spawn( "script_model", self geteye() + ( ( anglestoforward( self.angles ) * 100 ) ) );
self.debug_reflectionobject setmodel( "test_sphere_silver" );
self.debug_reflectionobject.origin = self geteye() + ( ( anglestoforward( self getplayerangles() ) * 100 ) );
self thread reflectionProbeButtons();
}
}
else if ( GetDvarInt( "debug_reflection" ) == 0 )
{
if ( IsDefined( self.debug_reflectionobject ) )
self.debug_reflectionobject delete();
}
wait( 0.05 );
}
}
reflectionProbeButtons()
{
offset = 100;
offsetinc = 50;
while ( GetDvarInt( "debug_reflection" ) == 1 )
{
if ( self buttonpressed( "BUTTON_X" ) )
offset += offsetinc;
if ( self buttonpressed( "BUTTON_Y" ) )
offset -= offsetinc;
if ( offset > 1000 )
offset = 1000;
if ( offset < 64 )
offset = 64;
self.debug_reflectionobject.origin = self GetEye() + ( ( AnglesToForward( self GetPlayerAngles() ) * offset ) );
wait .05;
}
}
#/

210
maps/mp/alien/_director.gsc Normal file
View File

@ -0,0 +1,210 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\agents\_agent_utility;
#include maps\mp\alien\_utility;
// ================================================================
// Alien Attribute Table
// ================================================================
ATTRIBUTE_TABLE = "mp/alien/default_alien_definition.csv";
TABLE_COL_INDEX = 0;
TABLE_COL_ATTRIBUTE = 1;
TABLE_COL_AI_TYPE_BEGIN = 2;
TABLE_COL_AI_TYPE_MAX_TYPES = 16;
alien_attribute_table_init()
{
// to be updated with default_alien_definition.csv
// value variable type is defined in index values
if ( !isdefined( level.default_alien_definition ) )
level.default_alien_definition = ATTRIBUTE_TABLE;
att_idx = [];
att_idx[ "ref" ] = "0"; // string value
att_idx[ "name" ] = "1";
att_idx[ "model" ] = "2";
att_idx[ "desc" ] = "3";
att_idx[ "boss" ] = 4; // int value
att_idx[ "animclass" ] = "5"; // string value
att_idx[ "health" ] = 10;
att_idx[ "min_cumulative_pain_threshold" ] = 11;
att_idx[ "min_cumulative_pain_buffer_time" ] = 12.0;
att_idx[ "accuracy" ] = 13.0; // float value
att_idx[ "speed" ] = 14.0;
att_idx[ "scale" ] = 15.0;
att_idx[ "xp" ] = 16;
att_idx[ "attacker_difficulty" ] = 17.0;
att_idx[ "attacker_priority" ] = 18;
att_idx[ "jump_cost" ] = 19.0;
att_idx[ "traverse_cost" ] = 20.0;
att_idx[ "run_cost" ] = 21.0;
att_idx[ "wall_run_cost" ] = 29.0;
att_idx[ "heavy_damage_threshold" ] = 22.0;
att_idx[ "pain_interval" ] = 23.0;
att_idx[ "emissive_default" ] = 24.0;
att_idx[ "emissive_max" ] = 25.0;
att_idx[ "weight_scale" ] = 26.0;
att_idx[ "reward" ] = 27.0;
att_idx[ "view_height" ] = 28.0;
att_idx[ "behavior_cloak" ] = 100;
att_idx[ "behavior_spit" ] = 101;
att_idx[ "behavior_lead" ] = 102;
att_idx[ "behavior_hives" ] = 103;
att_idx[ "swipe_min_damage" ] = 2000;
att_idx[ "swipe_max_damage" ] = 2001;
att_idx[ "leap_min_damage" ] = 2002;
att_idx[ "leap_max_damage" ] = 2003;
att_idx[ "wall_min_damage" ] = 2004;
att_idx[ "wall_max_damage" ] = 2005;
att_idx[ "charge_min_damage" ] = 2006;
att_idx[ "charge_max_damage" ] = 2007;
att_idx[ "explode_min_damage" ] = 2008;
att_idx[ "explode_max_damage" ] = 2009;
att_idx[ "slam_min_damage" ] = 2010;
att_idx[ "slam_max_damage" ] = 2011;
att_idx[ "synch_min_damage_per_second" ] = 2012;
att_idx[ "synch_max_damage_per_second" ] = 2013;
// loots - float values
loot_index = 1000;
loot_index_max = 1100;
for( i = loot_index; i < loot_index_max; i++ )
{
loot_ref = TableLookup( level.default_alien_definition, TABLE_COL_INDEX, i, TABLE_COL_ATTRIBUTE );
if ( loot_ref == "" )
break;
att_idx[ loot_ref ] = i * 1.00; // float
}
level.alien_types = [];
// get types from table
maxIndex = TABLE_COL_AI_TYPE_BEGIN + TABLE_COL_AI_TYPE_MAX_TYPES;
for ( typeIndex = TABLE_COL_AI_TYPE_BEGIN; typeIndex < maxIndex; typeIndex++ )
setup_alien_type( att_idx, typeIndex );
if ( IsDefined( level.custom_alien_attribute_table_init ) )
[[level.custom_alien_attribute_table_init]]();
}
setup_alien_type( att_idx, type )
{
type_ref = TableLookup( level.default_alien_definition, TABLE_COL_INDEX, att_idx[ "ref" ], type );
// return if type does not exist
if ( type_ref == "" )
return;
level.alien_types[ type_ref ] = SpawnStruct();
//level.alien_types[ type_ref ].attribute_index = att_idx;
level.alien_types[ type_ref ].attributes = [];
level.alien_types[ type_ref ].loots = [];
foreach( key, index in att_idx )
{
value = TableLookup( level.default_alien_definition, TABLE_COL_INDEX, index, type );
// cast the correct variable type
if ( !isString( index ) )
{
if ( !IsSubStr( value, "." ) )
value = int( value );
else
value = float( value );
}
level.alien_types[ type_ref ].attributes[ key ] = value;
// loot!
if ( IsSubStr( key, "loot_" ) && value > 0.0 )
{
level.alien_types[ type_ref ].loots[ key ] = value;
}
}
}
// ============== Alien cloaking ==============
CONST_DECLOAK_DIST = 800;
CONST_CLOCK_CHANCE = 1;
alien_cloak()
{
self endon( "death" );
self thread near_player_notify();
while ( 1 )
{
if( any_player_nearby( self.origin, CONST_DECLOAK_DIST ) )
{
wait 0.05;
continue;
}
self waittill( "jump_launching" );
wait 0.20;
original_model = self.model;
self maps\mp\alien\_alien_fx::alien_cloak_fx_on();
self cloak_fx();
self setmodel( original_model + "_cloak" ); // this _cloak model must exist
waittill_any_timeout( 1, "jump_finished", "damage" ); //, "near_player" );
wait 0.20;
//self Show();
self maps\mp\alien\_alien_fx::alien_cloak_fx_off();
self uncloak_fx();
self setmodel( original_model );
}
}
// WIP: SP>MP
near_player_notify()
{
self endon( "death" );
while ( 1 )
{
if ( any_player_nearby( self.origin, CONST_DECLOAK_DIST ) )
self notify( "near_player" );
wait 0.05;
}
}
cloak_fx()
{
PlayFXOnTag( level._effect[ "alien_cloaking" ], self, "j_neck" );
}
uncloak_fx()
{
PlayFXOnTag( level._effect[ "alien_uncloaking" ], self, "j_neck" );
}
smoke_puff()
{
PlayFXOnTag( level._effect[ "alien_teleport" ], self, "tag_origin" );
// somehow in MP the tags are not valid assets???
//PlayFXOnTag( level._effect[ "alien_teleport" ], self, "j_spineupper" );
//PlayFXOnTag( level._effect[ "alien_teleport" ], self, "j_mainroot" );
//PlayFXOnTag( level._effect[ "alien_teleport" ], self, "j_tail_3" );
PlayFXOnTag( level._effect[ "alien_teleport_dist" ], self, "tag_origin" );
}

2164
maps/mp/alien/_drill.gsc Normal file

File diff suppressed because it is too large Load Diff

21
maps/mp/alien/_ffotd.gsc Normal file
View File

@ -0,0 +1,21 @@
// FFOTD scripts for aliens
init()
{
}
onStartGameType()
{
}
onPlayerConnect()
{
}
onSpawnPlayer()
{
}
onSpawnAlien()
{
}

View File

@ -0,0 +1,918 @@
#include maps\mp\alien\_utility;
SCORE_TO_CASH_CONVERSION = 0.1; // the conversion rate from hive score( without prestige nerf bonus) to cash
PRESTIGE_RELIC_SCORE_BONUS = 0.2; // The extra percentage of hive score that player will earn for each prestige relic on
// LUA uses the index to lookup the actual string from scoreboard_string_lookup.csv
CONST_UI_STRING_INDEX_DRILL_PROTECT = 1; // "ALIEN_COLLECTIBLES_DRILL_PROTECT";
CONST_UI_STRING_INDEX_TEAMWORK = 2; // "ALIEN_COLLECTIBLES_TEAMWORK";
CONST_UI_STRING_INDEX_PERSONAL_SKILL = 3; // "ALIEN_COLLECTIBLES_PERSONAL_SKILL";
CONST_UI_STRING_INDEX_CHALLENGE = 4; // "ALIEN_COLLECTIBLES_CHALLENGE_COMP";
CONST_UI_STRING_INDEX_RELIC_BONUS = 5; // "ALIEN_COLLECTIBLES_PRESTIGE_BONUS";
CONST_UI_STRING_INDEX_TOTAL_SCORE = 6; // "ALIEN_COLLECTIBLES_HIVE_SCORE_EARNED";
CONST_UI_STRING_INDEX_BONUS_MONEY = 7; // "ALIEN_COLLECTIBLES_BONUS_MONEY_EARNED";
CONST_UI_STRING_INDEX_HIVE = 8; // "ALIEN_COLLECTIBLES_TOTAL_HIVE_SCORE";
CONST_UI_STRING_INDEX_ESCAPE = 9; // "ALIEN_COLLECTIBLES_ESCAPE_TIME_BONUS";
CONST_UI_STRING_INDEX_EOG_TOTAL_SCORE = 10; // "ALIEN_COLLECTIBLES_END_GAME_SCORE";
// Encounter score
CONST_NAME_REF_CHALLENGE = "challenge";
CONST_NAME_REF_DRILL = "drill";
CONST_NAME_REF_TEAM = "team";
CONST_NAME_REF_PERSONAL = "personal";
CONST_NAME_REF_ESCAPE = "escape";
CONST_NAME_REF_TEAM_BLK = "team_blocker";
CONST_NAME_REF_PERSONAL_BLK = "personal_blocker";
// EOG score
CONST_NAME_REF_EOG_HIVE = "hive";
CONST_NAME_REF_EOG_ESCAPE = "escape";
CONST_NAME_REF_EOG_RELICS = "relics";
init_gamescore()
{
register_scoring_mode();
}
init_eog_score_components( component_name_list )
{
level.eog_score_components = [];
foreach( component_name in component_name_list )
{
switch( component_name )
{
case CONST_NAME_REF_EOG_HIVE:
register_eog_score_component( CONST_NAME_REF_EOG_HIVE, CONST_UI_STRING_INDEX_HIVE );
break;
case CONST_NAME_REF_EOG_ESCAPE:
register_eog_score_component( CONST_NAME_REF_EOG_ESCAPE, CONST_UI_STRING_INDEX_ESCAPE );
break;
case CONST_NAME_REF_EOG_RELICS:
register_eog_score_component( CONST_NAME_REF_EOG_RELICS, CONST_UI_STRING_INDEX_RELIC_BONUS );
break;
default:
AssertMsg( "'" + component_name + "' is not a supported end-of-game score component." );
}
}
}
init_encounter_score_components( component_name_list )
{
level.encounter_score_components = [];
foreach( component_name in component_name_list )
{
switch( component_name )
{
case CONST_NAME_REF_CHALLENGE:
init_challenge_score_component();
break;
case CONST_NAME_REF_DRILL:
init_drill_score_component();
break;
case CONST_NAME_REF_TEAM:
init_teamwork_score_component();
break;
case CONST_NAME_REF_TEAM_BLK:
init_blocker_hive_teamwork_score_component();
break;
case CONST_NAME_REF_PERSONAL:
init_personal_score_component();
break;
case CONST_NAME_REF_PERSONAL_BLK:
init_blocker_hive_personal_score_component();
break;
case CONST_NAME_REF_ESCAPE:
init_escape_score_component();
break;
default:
AssertMsg( "'" + component_name + "' is not a supported round score component." );
}
}
}
init_player_score()
{
if ( is_scoring_disabled() )
return;
self.encounter_performance = [];
self.end_game_score = [];
component_specific_init( self );
reset_player_encounter_performance( self );
reset_end_game_score();
}
reset_encounter_performance()
{
foreach( component_name, score_component in level.encounter_score_components )
{
if ( isDefined( score_component.reset_team_performance_func ) )
[[score_component.reset_team_performance_func]]( score_component );
}
reset_players_encounter_performance_and_LUA();
}
reset_players_encounter_performance_and_LUA()
{
foreach( player in level.players )
{
reset_player_encounter_performance( player );
maps\mp\alien\_hud::reset_player_encounter_LUA_omnvars( player );
}
}
component_specific_init( player )
{
foreach( component_name, score_component in level.encounter_score_components )
{
if ( isDefined( score_component.player_init_func ) )
[[score_component.player_init_func]]( player );
}
}
reset_player_encounter_performance( player )
{
foreach( component_name, score_component in level.encounter_score_components )
{
if ( isDefined( score_component.reset_player_performance_func ) )
[[score_component.reset_player_performance_func]]( player );
}
}
reset_end_game_score()
{
foreach( eog_component_name, score_component in level.eog_score_components )
self.end_game_score[eog_component_name] = 0;
}
calculate_total_end_game_score( player )
{
row_number = 1;
total_end_game_score = 0;
foreach( eog_score_name, eog_score_component_struct in level.eog_score_components )
{
eog_score_value = player.end_game_score[eog_score_name];
maps\mp\alien\_hud::set_LUA_EoG_score_row( player, row_number, eog_score_component_struct.lua_string_index, eog_score_value );
row_number++;
total_end_game_score += eog_score_value;
}
maps\mp\alien\_hud::set_LUA_EoG_score_row( player, row_number, CONST_UI_STRING_INDEX_EOG_TOTAL_SCORE, total_end_game_score );
}
calculate_players_total_end_game_score()
{
if ( is_scoring_disabled() )
return;
if ( common_scripts\utility::flag_exist( "drill_drilling" ) && common_scripts\utility::flag( "drill_drilling" ) )
calculate_encounter_scores( level.players, get_partial_hive_score_component_list() ); // Partial hive
foreach ( player in level.players )
calculate_total_end_game_score( player );
}
get_partial_hive_score_component_list()
{
if ( isDefined( level.partial_hive_score_component_list_func ) )
return [[level.partial_hive_score_component_list_func]]();
return [ CONST_NAME_REF_CHALLENGE, CONST_NAME_REF_TEAM ];
}
update_players_encounter_performance( score_component_name, performance_type, amount )
{
foreach ( player in level.players )
player update_personal_encounter_performance( score_component_name, performance_type, amount );
}
calculate_and_show_encounter_scores( players_list, score_component_name_list )
{
calculate_encounter_scores( players_list, score_component_name_list );
maps\mp\alien\_hud::show_encounter_scores();
}
calculate_encounter_scores( players_list, score_component_name_list )
{
foreach( player in players_list )
calculate_player_encounter_scores( player, score_component_name_list );
}
calculate_player_encounter_scores( player, score_component_name_list )
{
/#
maps\mp\alien\_debug::debug_print_encounter_performance( player );
#/
row_number = 1;
total_score = 0;
foreach ( score_component_name in score_component_name_list )
{
AssertEx( isDefined( level.encounter_score_components[score_component_name] ), "'" + score_component_name + "' is not a initialized score component" );
score_component_struct = level.encounter_score_components[score_component_name];
encounter_score = [[score_component_struct.calculate_func]]( player, score_component_struct );
encounter_score *= level.cycle_score_scalar;
encounter_score = int( encounter_score );
player.end_game_score[score_component_struct.end_game_score_component_ref] += encounter_score; // Update the corresponding EoG score field
maps\mp\alien\_hud::set_LUA_encounter_score_row( player, row_number, score_component_struct.lua_string_index, encounter_score );
total_score += encounter_score;
row_number++;
}
// Relics bonus score
num_relic_selected = player maps\mp\alien\_prestige::get_num_nerf_selected();
relics_bonus_score = int( total_score * num_relic_selected * PRESTIGE_RELIC_SCORE_BONUS );
AssertEx( has_eog_score_component( CONST_NAME_REF_EOG_RELICS ), "'relics' needs to be initialized as one of the end-of-game score components" );
player.end_game_score["relics"] += relics_bonus_score;
maps\mp\alien\_hud::set_LUA_encounter_score_row( player, row_number, CONST_UI_STRING_INDEX_RELIC_BONUS, relics_bonus_score );
row_number++;
// Total encounter score
total_score += relics_bonus_score;
player maps\mp\alien\_persistence::eog_player_update_stat( "score", total_score ); // For in-game pause menu
maps\mp\alien\_hud::set_LUA_encounter_score_row( player, row_number, CONST_UI_STRING_INDEX_TOTAL_SCORE, total_score );
row_number++;
// Bonus cash earned
perk_currency_scalar = player maps\mp\alien\_perk_utility::perk_GetCurrencyScalePerHive();
prestige_currency_scalar = player maps\mp\alien\_prestige::prestige_getMoneyEarnedScalar();
bonus_cash_earned = int( total_score * perk_currency_scalar * prestige_currency_scalar * SCORE_TO_CASH_CONVERSION / level.cycle_score_scalar );
bonus_cash_earned = round_up_to_nearest( bonus_cash_earned, 10 );
maps\mp\alien\_hud::set_LUA_encounter_score_row( player, row_number, CONST_UI_STRING_INDEX_BONUS_MONEY, bonus_cash_earned );
player.encounter_score_earned = total_score;
player.encounter_cash_earned = bonus_cash_earned;
}
/////////////////////////////////////
// Challenge //
/////////////////////////////////////
COOP_CONST_MAX_SCORE_COMPLETE_CHALLENGE = 1000;
SOLO_CONST_MAX_SCORE_COMPLETE_CHALLENGE = 1500;
CONST_DEFAULT_CHALLENGE_COMPONENT_NAME = "challenge";
init_challenge_score_component()
{
register_encounter_score_component( CONST_NAME_REF_CHALLENGE,
::init_challenge_score,
undefined,
::reset_player_challenge_performance,
::calculate_challenge_score,
CONST_UI_STRING_INDEX_CHALLENGE,
CONST_NAME_REF_EOG_HIVE );
}
init_challenge_score( score_component_struct )
{
if ( isPlayingSolo() )
score_component_struct.max_score = SOLO_CONST_MAX_SCORE_COMPLETE_CHALLENGE;
else
score_component_struct.max_score = COOP_CONST_MAX_SCORE_COMPLETE_CHALLENGE;
return score_component_struct;
}
reset_player_challenge_performance( player )
{
player.encounter_performance["challenge_complete"] = 0;
}
calculate_challenge_score( player, score_component_struct )
{
return int( player.encounter_performance["challenge_complete"] * score_component_struct.max_score );
}
get_challenge_score_component_name() { return common_scripts\utility::ter_op( isDefined( level.challenge_score_component_name ), level.challenge_score_component_name, CONST_DEFAULT_CHALLENGE_COMPONENT_NAME ); }
set_challenge_score_component_name( challenge_score_component_name ) { level.challenge_score_component_name = challenge_score_component_name; }
/////////////////////////////////////
// Drill //
/////////////////////////////////////
COOP_CONST_MAX_SCORE_DRILL_DAMAGE = 3500;
SOLO_CONST_MAX_SCORE_DRILL_DAMAGE = 4500;
COOP_CONST_DRILL_DAMAGE_LIMIT = 750; // if the drill takes more damage than this, no score from drill damage taken ( 60% of max health )
SOLO_CONST_DRILL_DAMAGE_LIMIT = 1200; // if the drill takes more damage than this, no score from drill damage taken ( 60% of max health )
CONST_DEFAULT_DRILL_COMPONENT_NAME = "drill";
init_drill_score_component()
{
register_encounter_score_component( CONST_NAME_REF_DRILL,
::init_drill_score,
::reset_team_drill_performance,
undefined,
::calculate_drill_protection_score,
CONST_UI_STRING_INDEX_DRILL_PROTECT,
CONST_NAME_REF_EOG_HIVE );
}
init_drill_score( score_component_struct )
{
if ( isPlayingSolo() )
{
score_component_struct.max_score_damage_damage = SOLO_CONST_MAX_SCORE_DRILL_DAMAGE;
score_component_struct.max_drill_damage_limit = SOLO_CONST_DRILL_DAMAGE_LIMIT;
}
else
{
score_component_struct.max_score_damage_damage = COOP_CONST_MAX_SCORE_DRILL_DAMAGE;
score_component_struct.max_drill_damage_limit = COOP_CONST_DRILL_DAMAGE_LIMIT;
}
return score_component_struct;
}
reset_team_drill_performance( score_component_struct )
{
score_component_struct.team_encounter_performance["drill_damage_taken"] = 0;
return score_component_struct;
}
calculate_drill_protection_score( player, score_component_struct )
{
damage_penalty = get_team_encounter_performance( score_component_struct, "drill_damage_taken" ) / score_component_struct.max_drill_damage_limit ;
damage_score_percent_earned = max( 0, 1 - damage_penalty );
max_score_drill_damage = score_component_struct.max_score_damage_damage;
damage_score_earned = max_score_drill_damage * damage_score_percent_earned;
/#
maps\mp\alien\_debug::debug_print_drill_protection_score( damage_score_earned );
#/
return int( damage_score_earned );
}
get_drill_score_component_name() { return common_scripts\utility::ter_op( isDefined( level.drill_score_component_name ), level.drill_score_component_name, CONST_DEFAULT_DRILL_COMPONENT_NAME ); }
set_drill_score_component_name( drill_score_component_name ) { level.drill_score_component_name = drill_score_component_name; }
/////////////////////////////////////
// Team //
/////////////////////////////////////
COOP_CONST_MAX_SCORE_DEPLOY_SUPPORT = 1000;
COOP_CONST_MAX_SCORE_REVIVE_TEAMMATE = 1000;
COOP_CONST_MAX_SCORE_DAMAGE_DONE = 1000;
COOP_CONST_DEPLOY_SUPPORT = 100; // player gains this many point every time deploy a team support item
COOP_CONST_PENALTY_PER_DOWN = 200; // all players loses this many point every time a teammate goes down
CONST_DEFAULT_TEAM_COMPONENT_NAME = "team";
init_teamwork_score_component()
{
register_encounter_score_component( CONST_NAME_REF_TEAM,
::init_teamwork_score,
::reset_team_score_performance,
::reset_player_teamwork_score_performance,
::calculate_teamwork_score,
CONST_UI_STRING_INDEX_TEAMWORK,
CONST_NAME_REF_EOG_HIVE );
}
init_teamwork_score( score_component_struct )
{
score_component_struct.max_score_deploy = COOP_CONST_MAX_SCORE_DEPLOY_SUPPORT;
score_component_struct.max_score_revive = COOP_CONST_MAX_SCORE_REVIVE_TEAMMATE;
score_component_struct.max_score_damage = COOP_CONST_MAX_SCORE_DAMAGE_DONE;
reset_team_score_performance( score_component_struct );
return score_component_struct;
}
reset_team_score_performance( score_component_struct )
{
score_component_struct.team_encounter_performance["damage_done_on_alien"] = 0;
score_component_struct.team_encounter_performance["num_players_enter_laststand"] = 0;
score_component_struct.team_encounter_performance["num_players_bleed_out"] = 0;
return score_component_struct;
}
reset_player_teamwork_score_performance( player )
{
player.encounter_performance["damage_done_on_alien"] = 0;
player.encounter_performance["team_support_deploy"] = 0;
}
calculate_teamwork_score( player, score_component_struct )
{
max_score_deploy_support = score_component_struct.max_score_deploy;
deploy_supply_score_earned = min( max_score_deploy_support, get_player_encounter_performance( player, "team_support_deploy" ) * COOP_CONST_DEPLOY_SUPPORT );
if ( get_team_encounter_performance( score_component_struct, "num_players_bleed_out" ) )
{
revive_teammate_score_earned = 0;
}
else
{
max_score_revive = score_component_struct.max_score_revive;
total_penalty = get_team_encounter_performance( score_component_struct, "num_players_enter_laststand" ) * COOP_CONST_PENALTY_PER_DOWN;
revive_teammate_score_earned = max ( 0, ( max_score_revive - total_penalty ) );
}
team_damage_done_on_alien = get_team_encounter_performance( score_component_struct, "damage_done_on_alien" );
if ( team_damage_done_on_alien == 0 )
team_damage_done_on_alien = 1;
damage_done_ratio = get_player_encounter_performance( player, "damage_done_on_alien" ) / team_damage_done_on_alien;
max_score_damage_done = score_component_struct.max_score_damage;
damage_score_team_pool = max_score_damage_done * level.players.size;
damage_done_score_earned = min( max_score_damage_done, damage_done_ratio * damage_score_team_pool );
/#
maps\mp\alien\_debug::debug_print_teamwork_score( deploy_supply_score_earned, revive_teammate_score_earned, damage_done_score_earned );
#/
return int( deploy_supply_score_earned + revive_teammate_score_earned + damage_done_score_earned );
}
get_team_score_component_name() { return common_scripts\utility::ter_op( isDefined( level.team_score_component_name ), level.team_score_component_name, CONST_DEFAULT_TEAM_COMPONENT_NAME ); }
set_team_score_component_name( team_score_component_name ) { level.team_score_component_name = team_score_component_name; }
/////////////////////////////////////
// Blocker Hive: Team //
/////////////////////////////////////
COOP_CONST_MAX_BLOCKER_SCORE_DEPLOY_SUPPORT = 2000;
COOP_CONST_MAX_BLOCKER_SCORE_REVIVE_TEAMMATE = 1000;
COOP_CONST_MAX_BLOCKER_SCORE_DAMAGE_DONE = 2500;
init_blocker_hive_teamwork_score_component()
{
register_encounter_score_component( CONST_NAME_REF_TEAM_BLK,
::init_blocker_teamwork_score,
::reset_team_score_performance,
::reset_player_teamwork_score_performance,
::calculate_teamwork_score,
CONST_UI_STRING_INDEX_TEAMWORK,
CONST_NAME_REF_EOG_HIVE );
}
init_blocker_teamwork_score( score_component_struct )
{
score_component_struct.max_score_deploy = COOP_CONST_MAX_BLOCKER_SCORE_DEPLOY_SUPPORT;
score_component_struct.max_score_revive = COOP_CONST_MAX_BLOCKER_SCORE_REVIVE_TEAMMATE;
score_component_struct.max_score_damage = COOP_CONST_MAX_BLOCKER_SCORE_DAMAGE_DONE;
reset_team_score_performance( score_component_struct );
return score_component_struct;
}
////////////////////////////////////////
// Personal //
////////////////////////////////////////
COOP_CONST_MAX_SCORE_DAMAGE_TAKEN = 1500;
COOP_CONST_MAX_SCORE_ACCURACY = 1000;
SOLO_CONST_MAX_SCORE_DAMAGE_TAKEN = 2500;
SOLO_CONST_MAX_SCORE_ACCURACY = 1500;
CONST_PLAYER_DAMAGE_LIMIT = 500; // if player takes this much damage, no skill score from avoid damage
CONST_DEFAULT_PERSONAL_COMPONENT_NAME = "personal";
init_personal_score_component()
{
register_encounter_score_component( CONST_NAME_REF_PERSONAL,
::init_personal_score,
undefined,
::reset_player_personal_score_performance,
::calculate_personal_skill_score,
CONST_UI_STRING_INDEX_PERSONAL_SKILL,
CONST_NAME_REF_EOG_HIVE );
}
init_personal_score( score_component_struct )
{
if( isPlayingSolo() )
{
score_component_struct.max_score_damage_taken = SOLO_CONST_MAX_SCORE_DAMAGE_TAKEN;
score_component_struct.max_score_accuracy = SOLO_CONST_MAX_SCORE_ACCURACY;
}
else
{
score_component_struct.max_score_damage_taken = COOP_CONST_MAX_SCORE_DAMAGE_TAKEN;
score_component_struct.max_score_accuracy = COOP_CONST_MAX_SCORE_ACCURACY;
}
return score_component_struct;
}
reset_player_personal_score_performance( player )
{
player.encounter_performance["damage_taken"] = 0;
player.encounter_performance["shots_hit"] = 0;
player.encounter_performance["shots_fired"] = 0;
}
calculate_personal_skill_score( player, score_component_struct )
{
damage_penalty = get_player_encounter_performance( player, "damage_taken" ) / CONST_PLAYER_DAMAGE_LIMIT;
damage_score_percent_earned = max( 0, 1 - damage_penalty );
max_score_demage_taken = score_component_struct.max_score_damage_taken;
damage_score_earned = max_score_demage_taken * damage_score_percent_earned;
if ( get_player_encounter_performance( player, "shots_fired" ) == 0 )
accuracy_ratio = 1.0;
else
accuracy_ratio = get_player_encounter_performance( player, "shots_hit" ) / get_player_encounter_performance( player, "shots_fired" );
//AssertEx( accuracy_ratio <= 1.0, "Personal accuracy is greater than 100%. Need to exclude weapons that we cannot track misses." );
accuracy_ratio = min( 1.0, accuracy_ratio );
max_score_accuracy = score_component_struct.max_score_accuracy;
accuracy_score_earned = max_score_accuracy * accuracy_ratio;
/#
maps\mp\alien\_debug::debug_print_personal_skill_score( damage_score_earned, accuracy_score_earned );
#/
return int( damage_score_earned + accuracy_score_earned );
}
get_personal_score_component_name() { return common_scripts\utility::ter_op( isDefined( level.personal_score_component_name ), level.personal_score_component_name, CONST_DEFAULT_PERSONAL_COMPONENT_NAME ); }
set_personal_score_component_name( personal_score_component_name ) { level.personal_score_component_name = personal_score_component_name; }
////////////////////////////////////////
// Blocker Hive: Personal //
////////////////////////////////////////
COOP_CONST_MAX_BLOCKER_SCORE_DAMAGE_TAKEN = 2500;
COOP_CONST_MAX_BLOCKER_SCORE_ACCURACY = 2000;
SOLO_CONST_MAX_BLOCKER_SCORE_DAMAGE_TAKEN = 5500;
SOLO_CONST_MAX_BLOCKER_SCORE_ACCURACY = 4500;
init_blocker_hive_personal_score_component()
{
register_encounter_score_component( CONST_NAME_REF_PERSONAL_BLK,
::init_blocker_personal_score,
undefined,
::reset_player_personal_score_performance,
::calculate_personal_skill_score,
CONST_UI_STRING_INDEX_PERSONAL_SKILL,
CONST_NAME_REF_EOG_HIVE );
}
init_blocker_personal_score( score_component_struct )
{
if( isPlayingSolo() )
{
score_component_struct.max_score_damage_taken = SOLO_CONST_MAX_BLOCKER_SCORE_DAMAGE_TAKEN;
score_component_struct.max_score_accuracy = SOLO_CONST_MAX_BLOCKER_SCORE_ACCURACY;
}
else
{
score_component_struct.max_score_damage_taken = COOP_CONST_MAX_BLOCKER_SCORE_DAMAGE_TAKEN;
score_component_struct.max_score_accuracy = COOP_CONST_MAX_BLOCKER_SCORE_ACCURACY;
}
return score_component_struct;
}
/////////////////////////////////////////
// Escape //
/////////////////////////////////////////
CONST_TOTAL_ESCAPE_TIME_IN_MS = 240000;
CONST_MAX_ESCAPE_SCORE = 15000;
CONST_ESCAPE_BASE_BONUS = 15000;
init_escape_score_component()
{
register_encounter_score_component( CONST_NAME_REF_ESCAPE,
::init_escape_score,
undefined,
undefined,
::calculate_escape_score,
CONST_UI_STRING_INDEX_ESCAPE,
CONST_NAME_REF_EOG_ESCAPE );
}
init_escape_score( score_component_struct )
{
score_component_struct.team_encounter_performance["time_remain_ms"] = 0;
score_component_struct.team_encounter_performance["escape_player_ratio"] = 0;
return score_component_struct;
}
calculate_escape_score( player, score_component_struct )
{
time_left_as_total_time = get_team_encounter_performance( score_component_struct, "time_remain_ms" ) / CONST_TOTAL_ESCAPE_TIME_IN_MS;
prestige_score_buff_scalar = 1 + ( player maps\mp\alien\_prestige::get_num_nerf_selected() + 1 ) * PRESTIGE_RELIC_SCORE_BONUS;
escape_time_score = int( CONST_ESCAPE_BASE_BONUS + CONST_MAX_ESCAPE_SCORE * time_left_as_total_time * get_team_encounter_performance( score_component_struct, "escape_player_ratio" ) * prestige_score_buff_scalar );
return escape_time_score;
}
process_end_game_score_escaped( escape_time_remains, players_escaped )
{
escape_player_ratio = players_escaped.size / level.players.size;
update_team_encounter_performance( "escape", "time_remain_ms", escape_time_remains );
update_team_encounter_performance( "escape", "escape_player_ratio", escape_player_ratio );
calculate_encounter_scores( players_escaped, [ CONST_NAME_REF_ESCAPE ] );
}
/////////////////////////////////////////
// Common helper funcs //
/////////////////////////////////////////
update_personal_encounter_performance( score_component_name, performance_type, amount )
{
if ( !has_encounter_score_component( score_component_name ) )
return;
if ( !isPlayer( self ) )
return;
self.encounter_performance = update_encounter_performance_internal( self.encounter_performance, performance_type, amount );
}
update_team_encounter_performance( score_component_name, performance_type, amount )
{
if ( !has_encounter_score_component( score_component_name ) )
return;
if ( !isDefined( amount ) )
amount = 1;
level.encounter_score_components[score_component_name].team_encounter_performance[performance_type] += amount;
}
update_encounter_performance_internal( performance_list, performance_type, amount )
{
AssertEx( isDefined( performance_list ), "Performance list is not defined" );
AssertEx( isDefined( performance_list[performance_type] ), "Unknown performance type: " + performance_type );
if ( !isDefined( amount ) )
amount = 1;
performance_list[performance_type] += amount;
return performance_list;
}
register_scoring_mode()
{
if ( isPlayingSolo() )
SetOmnvar( "ui_alien_is_solo", true );
else
SetOmnvar( "ui_alien_is_solo", false );
}
get_team_encounter_performance( score_component_struct, performance_type )
{
return score_component_struct.team_encounter_performance[performance_type];
}
get_player_encounter_performance( player, performance_type )
{
return player.encounter_performance[performance_type];
}
has_encounter_score_component( score_component_name )
{
return has_score_component_internal( level.encounter_score_components, score_component_name );
}
has_eog_score_component( score_component_name )
{
return has_score_component_internal( level.eog_score_components, score_component_name );
}
has_score_component_internal( score_component_list, score_component_name )
{
if ( is_scoring_disabled() )
return false;
return isDefined( score_component_list[score_component_name] );
}
register_eog_score_component( name_ref, lua_string_index )
{
score_component = spawnStruct();
score_component.lua_string_index = lua_string_index;
level.eog_score_components[name_ref] = score_component;
}
register_encounter_score_component( name_ref, init_func, reset_team_performance_func, reset_player_performance_func, calculate_func, lua_string_index, end_game_score_component_ref, player_init_func )
{
AssertEx( has_eog_score_component( end_game_score_component_ref ), "'" + end_game_score_component_ref + "' eog game component has not been registered." );
score_component = spawnStruct();
score_component = [[init_func]]( score_component );
score_component.reset_team_performance_func = reset_team_performance_func;
score_component.reset_player_performance_func = reset_player_performance_func;
score_component.calculate_func = calculate_func;
score_component.lua_string_index = lua_string_index;
score_component.end_game_score_component_ref = end_game_score_component_ref;
if ( isDefined( player_init_func ) )
score_component.player_init_func = player_init_func;
level.encounter_score_components[name_ref] = score_component;
}
update_performance_alien_damage( eAttacker, iDamage, sMeansOfDeath )
{
if ( !isDefined( eAttacker ) )
return;
if ( isDefined( eAttacker.classname ) && eAttacker.classname == "script_vehicle" ) // Friendly helicopter
return;
if ( sMeansOfDeath == "MOD_TRIGGER_HURT" ) // Kill trigger
return;
update_team_encounter_performance( get_team_score_component_name(), "damage_done_on_alien", iDamage );
personal_score_component_name = get_personal_score_component_name();
if ( isPlayer( eAttacker ) )
eAttacker update_personal_encounter_performance( personal_score_component_name, "damage_done_on_alien", iDamage );
else if ( isDefined( eAttacker.owner ) )
eAttacker.owner update_personal_encounter_performance( personal_score_component_name, "damage_done_on_alien", iDamage );
}
give_attacker_kill_rewards( attacker, sHitloc )
{
// if ( alien_mode_has( "nogame" ) )
// return;
if ( self.agentteam == "allies" )
return;
// For the elite, give all players the kill reward
if ( self get_alien_type() == "elite" || self get_alien_type() == "mammoth" )
{
reward_point = get_reward_point_for_kill();
foreach ( player in level.players )
{
self giveKillReward( player, reward_point, "large" );
}
return;
}
// Give assist bonuses
if ( isDefined( self.attacker_damage ) )
{
MIN_ASSIST_BONUS_DAMAGE_RATIO = 0.1;
min_assist_damage = self.max_health * MIN_ASSIST_BONUS_DAMAGE_RATIO;
assist_bonus_amount = self getAssistBonusAmount();
foreach ( attacker_struct in self.attacker_damage )
{
if ( attacker_struct.player == attacker ||( isDefined( attacker.owner ) && attacker_struct.player == attacker.owner ) )
continue;
if ( attacker_struct.damage >= min_assist_damage )
{
if ( IsDefined( attacker_struct.player ) && attacker_struct.player != attacker )
{
assertex( isplayer( attacker_struct.player ), "Tried to give non-player rewards" );
// EoG tracking: assists
attacker_struct.player maps\mp\alien\_persistence::eog_player_update_stat( "assists", 1 );
self giveKillReward( attacker_struct.player, assist_bonus_amount );
}
}
}
}
if ( !isDefined( attacker ) )
return;
if ( !isPlayer( attacker ) && ( !isDefined( attacker.owner ) || !isPlayer( attacker.owner ) ) )
return;
isEquipmentKill = false;
if ( isDefined( attacker.owner ) )
{
attacker = attacker.owner;
isEquipmentKill = true;
}
reward_point = get_reward_point_for_kill();
if ( isDefined ( sHitloc ) && sHitloc == "soft" && !isEquipmentKill )
reward_point = int( reward_point * 1.5 );
giveKillReward( attacker, reward_point, "large", sHitloc );
}
giveKillReward( attacker, amount, size, sHitloc )
{
currency_reward = amount * level.cycle_reward_scalar;
attacker maps\mp\alien\_persistence::give_player_currency( currency_reward, size, sHitloc );
// give xp
if( isdefined( level.alien_xp ) )
{
attacker maps\mp\alien\_persistence::give_player_xp( int( currency_reward ) );
}
// Add to cortex charge if applicable
if ( common_scripts\utility::flag_exist( "cortex_started" ) && common_scripts\utility::flag( "cortex_started" ) )
{
if ( IsDefined( level.add_cortex_charge_func ) )
{
[[level.add_cortex_charge_func]]( amount );
}
}
}
giveAssistBonus( attacker, damage )
{
if ( !isDefined( attacker ) )
return;
if ( !isPlayer( attacker ) && ( !isDefined( attacker.owner ) || !isPlayer( attacker.owner ) ) )
return;
if ( isDefined( attacker.owner ) )
attacker = attacker.owner;
if ( !IsDefined( self.attacker_damage ) )
{
self.attacker_damage = [];
}
foreach ( attacker_struct in self.attacker_damage )
{
if ( attacker_struct.player == attacker )
{
attacker_struct.damage += damage;
return;
}
}
new_attacker_struct = spawnstruct();
new_attacker_struct.player = attacker;
new_attacker_struct.damage = damage;
self.attacker_damage[ self.attacker_damage.size ] = new_attacker_struct;
}
getAssistBonusAmount()
{
return level.alien_types[ self get_alien_type() ].attributes["reward"] * 0.5;
}
get_reward_point_for_kill()
{
return level.alien_types[ self get_alien_type() ].attributes["reward"];
}
round_up_to_nearest( cash_amount, base )
{
temp_value = cash_amount / base;
temp_value = ceil( temp_value );
return int( temp_value * base );
}
is_scoring_disabled()
{
/#
if ( alien_mode_has( "nogame" ) )
return true;
if ( maps\mp\alien\_debug::spawn_test_enable() )
return true;
#/
if ( is_chaos_mode() )
return true; // Chaos has its own scoring system
return false;
}
////////////////////////////////
// Helper //
////////////////////////////////
// The more under the max limit, the higher the score
calculate_under_max_score( performance, max_limit, max_score )
{
under_max_limit = clamp( max_limit - performance, 0, max_limit );
return int ( under_max_limit / max_limit * max_score );
}

View File

@ -0,0 +1,268 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
init()
{
level.splitscreen = isSplitScreen();
set_console_status();
level.onlineGame = getDvarInt( "onlinegame" );
level.rankedMatch = ( ( level.onlineGame && !getDvarInt( "xblive_privatematch" ) ) || GetDvarInt( "force_ranking" ) ); // System link games are no longer ranked games
/#
if ( getdvarint( "scr_forcerankedmatch" ) == 1 )
{
level.onlineGame = true;
level.rankedMatch = true;
}
#/
level.script = toLower( getDvar( "mapname" ) );
level.gametype = toLower( getDvar( "g_gametype" ) );
//default team list, use this for team algos, overwrite it for Multiteam games
level.teamNameList = ["axis", "allies"];
level.otherTeam["allies"] = "axis";
level.otherTeam["axis"] = "allies";
level.multiTeamBased = false;
level.teamBased = false;
level.objectiveBased = false;
level.endGameOnTimeLimit = true;
level.showingFinalKillcam = false;
level.tiSpawnDelay = getDvarInt( "scr_tispawndelay" );
// hack to allow maps with no scripts to run correctly
if ( !isDefined( level.tweakablesInitialized ) )
maps\mp\gametypes\_tweakables::init();
level.halftimeType = "halftime";
level.halftimeSubCaption = &"MP_SWITCHING_SIDES";
level.lastStatusTime = 0;
level.wasWinning = "none";
level.lastSlowProcessFrame = 0;
level.placement["allies"] = [];
level.placement["axis"] = [];
level.placement["all"] = [];
level.postRoundTime = 5.0;
level.playersLookingForSafeSpawn = [];
registerDvars();
mapLeaderboard = " LB_" + getdvar( "ui_mapname" );
if(GetDvarInt( "scr_chaos_mode") == 1)
mapLeaderboard += "_CHAOS";
if( getDvarInt ( "sv_maxclients" ) == 1 )
mapLeaderboard += "_SOLO";
else
mapLeaderboard += "_COOP";
mapEscapesLeaderboard = " LB_" + getdvar( "ui_mapname" ) + "_ESCAPES";
if( getDvarInt( "scr_aliens_hardcore" ) )
mapLeaderboard += "_HC";
if(GetDvarInt( "scr_chaos_mode") == 1)
{
globalLeaderboard = "LB_GB_ALIEN_CHAOS";
if( getDvarInt ( "sv_maxclients" ) == 1 )
globalLeaderboard += "_SOLO";
else
globalLeaderboard += "_COOP";
precacheLeaderboards( globalLeaderboard + mapLeaderboard);
}
else
precacheLeaderboards( "LB_GB_ALIEN_HIVES LB_GB_ALIEN_KILLS LB_GB_ALIEN_REVIVES LB_GB_ALIEN_DOWNED LB_GB_ALIEN_XP LB_GB_ALIEN_SCORE LB_GB_ALIEN_CHALLENGES LB_GB_ALIEN_CASHFLOW" + mapLeaderboard + mapEscapesLeaderboard);
level.teamCount["allies"] = 0;
level.teamCount["axis"] = 0;
level.teamCount["spectator"] = 0;
level.aliveCount["allies"] = 0;
level.aliveCount["axis"] = 0;
level.aliveCount["spectator"] = 0;
level.livesCount["allies"] = 0;
level.livesCount["axis"] = 0;
level.oneLeftTime = [];
level.hasSpawned["allies"] = 0;
level.hasSpawned["axis"] = 0;
/#
if ( getdvarint( "scr_runlevelandquit" ) == 1 )
{
thread runLevelAndQuit();
}
#/
max_possible_teams = 9;
init_multiTeamData( max_possible_teams );
}
init_multiTeamData( max_num_teams )
{
for( i = 0; i < max_num_teams; i++ )
{
team_name = "team_" + i;
level.placement[team_name] = [];
level.teamCount[team_name] = 0;
level.aliveCount[team_name] = 0;
level.livesCount[team_name] = 0;
level.hasSpawned[team_name] = 0;
}
}
/#
runLevelAndQuit()
{
wait 1;
while ( level.players.size < 1 )
{
wait 0.5;
}
wait 0.5;
level notify( "game_ended" );
exitLevel();
}
#/
registerDvars()
{
SetOmnvar( "ui_bomb_timer", 0 );
if( getDvar( "r_reflectionProbeGenerate" ) != "1" )
{
SetOmnvar( "ui_nuke_end_milliseconds", 0 );
}
SetDvar( "ui_danger_team", "" );
SetDvar( "ui_inhostmigration", 0 );
SetDvar( "ui_inprematch", 0 );
SetDvar( "ui_override_halftime", 0 );
SetDvar( "camera_thirdPerson", getDvarInt( "scr_thirdPerson" ) );
SetDvar( "scr_alien_intel_pillage", 0 );
}
SetupCallbacks()
{
level.onXPEvent = ::onXPEvent;
level.getSpawnPoint = ::blank;
level.onSpawnPlayer = ::blank;
level.onRespawnDelay = ::blank;
level.onTimeLimit = maps\mp\gametypes\_gamelogic::default_onTimeLimit;
level.onHalfTime = maps\mp\gametypes\_gamelogic::default_onHalfTime;
level.onDeadEvent = maps\mp\gametypes\_gamelogic::default_onDeadEvent;
level.onOneLeftEvent = maps\mp\gametypes\_gamelogic::default_onOneLeftEvent;
level.onPrecacheGametype = ::blank;
level.onStartGameType = ::blank;
level.onPlayerKilled = ::blank;
level.killStreakInit = ::blank;
level.matchEventsInit = ::blank;
level.intelInit = ::blank;
/#
level.devInit = maps\mp\alien\_dev::init;
#/
}
blank( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 )
{
}
/#
xpRateThread()
{
self endon ( "death" );
self endon ( "disconnect" );
level endon ( "game_ended" );
gameFlagWait( "prematch_done" );
for ( ;; )
{
wait ( 5.0 );
if ( level.players[0].pers["team"] == "allies" || level.players[0].pers["team"] == "axis" )
self maps\mp\gametypes\_rank::giveRankXP( "kill", int(min( getDvarInt( "scr_xprate" ), 50 )) );
}
}
#/
testMenu()
{
self endon ( "death" );
self endon ( "disconnect" );
for ( ;; )
{
wait ( 10.0 );
notifyData = spawnStruct();
notifyData.titleText = &"MP_CHALLENGE_COMPLETED";
notifyData.notifyText = "wheee";
notifyData.sound = "mp_challenge_complete";
self thread maps\mp\gametypes\_hud_message::notifyMessage( notifyData );
}
}
testShock()
{
self endon ( "death" );
self endon ( "disconnect" );
for ( ;; )
{
wait ( 3.0 );
numShots = randomInt( 6 );
for ( i = 0; i < numShots; i++ )
{
iPrintLnBold( numShots );
self shellShock( "frag_grenade_mp", 0.2 );
wait ( 0.1 );
}
}
}
onXPEvent( event )
{
//self thread maps\mp\_loot::giveMoney( event, 10 );
self thread maps\mp\gametypes\_rank::giveRankXP( event );
}
debugLine( start, end )
{
for ( i = 0; i < 50; i++ )
{
line( start, end );
wait .05;
}
}

1148
maps/mp/alien/_hive.gsc Normal file

File diff suppressed because it is too large Load Diff

597
maps/mp/alien/_hud.gsc Normal file
View File

@ -0,0 +1,597 @@
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\alien\_persistence;
#include maps\mp\alien\_perk_utility;
//<TODO JC> When ship, all of those HUD elements should be replaced/handled by LUA
CREDIT_GAIN_DEFAULT_FONT_SIZE = 1.38;
SPLITSCREEN_CREDIT_GAIN_DEFAULT_FONT_SIZE = 1.2;
init()
{
register_end_game_string_index();
}
playPainOverlay( attacker, weapon_name, direction )
{
// No pain overlay for the player while in Vanguard
if ( isUsingRemote() && maps\mp\alien\_utility::is_true( self.vanguard_num ) )
return;
damage_direction = get_damage_direction( direction );
if ( is_spitter_spit( weapon_name ) ) {
self play_spitter_pain_overlay(damage_direction);
} else if ( is_spitter_gas( weapon_name ) ) {
self play_spitter_pain_overlay( "center" );
} else if ( is_elite_attack( attacker ) ) {
// play_slash_pain_overlay( damage_direction );
PlayFXOnTagForClients( level._effect[ "vfx_melee_blood_spray" ], self, "tag_eye", self );
} else {
self play_basic_pain_overlay( damage_direction );
}
}
get_damage_direction( direction )
{
COS_15 = 0.965;
possible_directions = ["left", "center", "right"];
if ( !isDefined( direction ) )
return possible_directions[randomInt( possible_directions.size )];
direction *= -1; //change direction to be based on the player's view
self_forward = anglesToForward( self.angles );
forward_dot_product = VectorDot( direction, self_forward );
if ( forward_dot_product > COS_15 )
return "center";
self_right = anglesToRight( self.angles );
right_dot_product = VectorDot( direction, self_right );
if ( right_dot_product > 0 )
return "right";
else
return "left";
}
play_basic_pain_overlay( damage_direction )
{
if ( damage_direction == "left" )
PlayFXOnTagForClients( level._effect[ "vfx_blood_hit_left" ], self, "tag_eye", self );
else if ( damage_direction == "center" )
PlayFXOnTagForClients( level._effect[ "vfx_melee_blood_spray" ], self, "tag_eye", self );
else if ( damage_direction == "right" )
PlayFXOnTagForClients( level._effect[ "vfx_blood_hit_right" ], self, "tag_eye", self );
else
AssertMsg( "Unknown damage_direction: " + damage_direction );
}
play_spitter_pain_overlay( damage_direction )
{
if ( damage_direction == "left" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_left" ], self, "tag_eye", self );
else if ( damage_direction == "center" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_center" ], self, "tag_eye", self );
else if ( damage_direction == "right" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_right" ], self, "tag_eye", self );
else
AssertMsg( "Unknown damage_direction: " + damage_direction );
}
play_slash_pain_overlay( damage_direction )
{
if ( damage_direction == "center" ) // We currently do not have a center HUD overlay for slash center
damage_direction = random_pick_R_or_L();
if ( damage_direction == "left" )
PlayFXOnTagForClients( level._effect[ "vfx_blood_hit_left" ], self, "tag_eye", self );
else if ( damage_direction == "right" )
PlayFXOnTagForClients( level._effect[ "vfx_blood_hit_right" ], self, "tag_eye", self );
else
AssertMsg( "Unknown damage_direction: " + damage_direction );
}
play_goo_pain_overlay( damage_direction )
{
if ( damage_direction == "left" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_left" ], self, "tag_eye", self );
else if ( damage_direction == "center" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_center" ], self, "tag_eye", self );
else if ( damage_direction == "right" )
PlayFXOnTagForClients( level._effect[ "vfx_alien_spitter_hit_right" ], self, "tag_eye", self );
else
AssertMsg( "Unknown damage_direction: " + damage_direction );
}
random_pick_R_or_L()
{
if ( cointoss() )
return "right";
else
return "left";
}
is_spitter_spit( weapon_name )
{
if ( !isDefined( weapon_name ) )
return false;
return ( weapon_name == "alienspit_mp" );
}
is_spitter_gas( weapon_name )
{
if ( !isDefined( weapon_name ) )
return false;
return ( weapon_name == "alienspit_gas_mp" );
}
is_elite_attack( attacker )
{
if ( !isDefined( attacker ) || !attacker maps\mp\alien\_utility::is_alien_agent() )
return false;
return ( attacker maps\mp\alien\_utility::get_alien_type() == "elite" );
}
//===========================================
// lastStandUpdateReviveIconColorAlien
//===========================================
lastStandUpdateReviveIconColorAlien( bleedOutTime )
{
self endon( "death" );
level endon( "game_ended" );
wait bleedOutTime / 3;
self.color = (1.0, 0.64, 0.0);
wait bleedOutTime / 3;
self.color = (1.0, 0.0, 0.0);
}
makeReviveIcon( owner, color, bleedOutTime )
{
reviveIcon = newTeamHudElem( owner.team );
reviveIcon setShader( "waypoint_alien_revive", 8, 8 );
reviveIcon setWaypoint( true, true );
reviveIcon SetTargetEnt( self );
reviveIcon.color = color;
reviveIcon thread deleteReviveIcon( owner );
if ( isDefined ( bleedOutTime ) )
reviveIcon thread lastStandUpdateReviveIconColorAlien( bleedOutTime );
return reviveIcon;
}
deleteReviveIcon( owner )
{
self endon ( "death" );
owner waittill_any( "disconnect", "revive", "death" );
self destroy();
}
hideHudElementOnGameEnd( hudElement )
{
level waittill("game_ended");
if ( isDefined( hudElement ) )
hudElement.alpha = 0;
}
blocker_hive_hp_bar()
{
submitted_health = 100000; // initial large value to get through initial delta comparison
while ( isdefined( self ) && self.health > 0 )
{
self waittill_notify_or_timeout( "damage", 2 );
if ( !isDefined ( self ) || self.health <= 0 )
break;
hp_ratio = max( 0.005, self.health / self.maxhealth );
inverse_health = 100 - hp_ratio * 100;
// omnvar throttle
throttle = 0.5;
if ( abs( abs( submitted_health ) - abs( inverse_health ) ) > throttle )
{
// inverse_health is ( max - health remaining ) for LUI
SetOmnvar ( "ui_alien_boss_progression", inverse_health );
submitted_health = inverse_health;
}
}
SetOmnvar ( "ui_alien_boss_status", 0 );
}
blocker_hive_chopper_hp_bar()
{
while ( isdefined( self ) && self.health > 0 )
{
self waittill_notify_or_timeout( "damage", 2 );
if ( !isDefined ( self ) || self.health <= 0 )
break;
hp_ratio = self.health / self.maxhealth;
health_remaining = hp_ratio * 100;
}
}
init_player_hud_onconnect()
{
VisionSetPain( "near_death_mp" );
/#
self.hud_laststand_count = self create_hud_laststand_count( 0, -20, 1.0 );
#/
}
/#
// Temp HUD for displaying the number of times the player drops into last stand
create_hud_laststand_count( xpos, ypos, scale )
{
self.hud_laststand_counter = 0;
hud_score = self maps\mp\gametypes\_hud_util::createFontString( "objective", scale );
hud_score maps\mp\gametypes\_hud_util::setPoint( "BOTTOM LEFT", "BOTTOM LEFT", xpos, ypos );
hud_score.color = ( 1, 1, 0 );
hud_score.glowAlpha = 1;
hud_score.sort = 1;
hud_score.hideWhenInMenu = true;
hud_score.archived = true;
hud_score.label = &"";
hud_score setValue( 0 );
if ( getDvarInt( "debug_alien_laststand_hud", 0 ) == 1 )
hud_score.alpha = 1;
else
hud_score.alpha = 0;
return hud_score;
}
update_hud_laststand_count()
{
self.hud_laststand_counter++;
self.hud_laststand_count setValue( self.hud_laststand_counter );
}
#/
createSpendHintHUD( resource, rank ,message )
{
if ( !isDefined ( message ) )
self setLowerMessage( "spend_hint", &"ALIEN_COLLECTIBLES_PULL_TO_SPEND" );
else
self setLowerMessage( "spend_hint", message );
self thread hideSpendHintIcon();
}
hideSpendHintIcon()
{
self endon ( "death" );
self endon ( "disconnect" );
self waittill_any_timeout( 3, "action_finish_used","player_action_slot_restart", "kill_spendhint" );
self clearLowerMessage( "spend_hint" );
}
intro_black_screen()
{
self endon( "disconnect" );
self endon( "stop_intro" );
self.introscreen_overlay = newClientHudElem( self );
self.introscreen_overlay.x = 0;
self.introscreen_overlay.y = 0;
self.introscreen_overlay setshader( "black", 640, 480 );
self.introscreen_overlay.alignX = "left";
self.introscreen_overlay.alignY = "top";
self.introscreen_overlay.sort = 1;
self.introscreen_overlay.horzAlign = "fullscreen";
self.introscreen_overlay.vertAlign = "fullscreen";
self.introscreen_overlay.alpha = 1;
self.introscreen_overlay.foreground = true;
level waittill( "introscreen_over" );
self.introscreen_overlay FadeOverTime( 3 );
self.introscreen_overlay.alpha = 0;
wait ( 3.5);
self.introscreen_overlay Destroy();
}
introscreen_corner_line( string, index_key )
{
if ( !IsDefined( level.intro_offset ) )
level.intro_offset = 0;
else
level.intro_offset++;
y = cornerline_height();
font_scale = 1.6;
if ( level.splitscreen )
font_scale = 2;
hudelem = NewHudElem();
hudelem.x = 20;
hudelem.y = y;
hudelem.alignX = "left";
hudelem.alignY = "bottom";
hudelem.horzAlign = "left";
hudelem.vertAlign = "bottom";
hudelem.sort = 3;// force to draw after the background
hudelem.foreground = true;
hudelem SetText( string );
hudelem.alpha = 1;
hudelem.hidewheninmenu = true;
hudelem.fontScale = font_scale;// was 1.6 and 2.4, larger font change
hudelem.color = ( 0.8, 1.0, 0.8 );
hudelem.font = "default";
hudelem.glowColor = ( 0.3, 0.6, 0.3 );
hudelem.glowAlpha = 1;
hudelem setPulseFX( 35, 4000, 1000 );
return hudelem;
}
cornerline_height()
{
offset = -92;
if ( level.splitscreen )
offset = -110;
return( ( ( level.intro_offset ) * 20 ) - 92 );
}
displayAlienGameEnd( winner, endReasonTextIndex )
{
foreach ( player in level.players )
{
if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
continue;
player thread alienOutcomeNotify( winner, endReasonTextIndex );
player thread freezeControlsWrapper( true );
}
level notify ( "game_win", winner );
maps\mp\gametypes\_gamelogic::roundEndWait( level.postRoundTime, true );
}
alienOutcomeNotify( winner, end_reason_text_index )
{
self endon ( "disconnect" );
self notify ( "reset_outcome" );
wait ( 0.5 );
team = self.pers["team"];
if ( !IsDefined( team ) || (team != "allies" && team != "axis") )
team = "allies";
// wait for notifies to finish
while ( self maps\mp\gametypes\_hud_message::isDoingSplash() )
wait 0.05;
self endon ( "reset_outcome" );
if ( IsDefined( self.pers["team"] ) && winner == team )
outcome_title_index = get_end_game_string_index( "win" );
else
outcome_title_index = get_end_game_string_index( "fail" );
self setClientOmnvar( "ui_round_end_title" , outcome_title_index );
self setClientOmnvar( "ui_round_end_reason" , end_reason_text_index );
self setClientOmnvar( "ui_alien_show_eog_score", true );
}
register_end_game_string_index()
{
if ( isDefined( level.end_game_string_override ) )
[[ level.end_game_string_override ]]();
else
register_default_end_game_string_index();
}
register_default_end_game_string_index()
{
level.end_game_string_index = [];
//<NOTE J.C.> When LUA is ready to take over, those string references will be changed into indexes and set via
// proper omnvar. The actual string references are in RoundEndHud.lua
// for ui_round_end_title
level.end_game_string_index["win"] = 1; // &"ALIEN_COLLECTIBLES_MISSION_WIN";
level.end_game_string_index["fail"] = 2; // &"ALIEN_COLLECTIBLES_MISSION_FAIL";
// for ui_round_end_reason
level.end_game_string_index["all_escape"] = 1; // &"ALIEN_COLLECTIBLES_MISSION_WIN_ALL_ESCAPE";
level.end_game_string_index["some_escape"] = 2; // &"ALIEN_COLLECTIBLES_MISSION_WIN_CASUALTY";
level.end_game_string_index["fail_escape"] = 3; // &"ALIEN_COLLECTIBLES_MISSION_FAIL_ESCAPE";
level.end_game_string_index["drill_destroyed"] = 4; // &"ALIEN_COLLECTIBLES_MISSION_FAIL_DRILL_DESTROYED";
level.end_game_string_index["kia"] = 5; // &"ALIEN_COLLECTIBLES_MISSION_FAIL_KILLED_IN_ACTION";
level.end_game_string_index["host_end"] = 6; // &"ALIEN_COLLECTIBLES_MISSION_FAIL_HOST_END";
level.end_game_string_index["gas_fail"] = 7; // &"ALIEN_PICKUPS_BEACON_GAS_FAIL";
level.end_game_string_index["generator_destroyed"] = 8; // &"MP_ALIEN_LAST_GENERATOR_DESTROYED";
}
get_end_game_string_index( key )
{
return level.end_game_string_index[key];
}
show_encounter_scores()
{
level endon( "game_ended " );
SetOmnvar( "ui_alien_show_encounter_score", true );
wait 1.0; // Allow LUI to catch the change notification
SetOmnvar( "ui_alien_show_encounter_score", false );
}
reset_player_encounter_LUA_omnvars( player )
{
CONST_ENCOUNTER_SCORE_MAX_NUM_ROW = 8;
for ( row_number = 1; row_number <= CONST_ENCOUNTER_SCORE_MAX_NUM_ROW; row_number++ )
{
title_omnvar_name = "ui_alien_encounter_title_row_" + row_number;
score_omnvar_name = "ui_alien_encounter_score_row_" + row_number;
player setClientOmnvar( title_omnvar_name, 0 );
player setClientOmnvar( score_omnvar_name, 0 );
}
}
set_LUA_encounter_score_row( player, row_number, row_title, row_score )
{
omnvar_title_name = "ui_alien_encounter_title_row_" + row_number;
omnvar_score_name = "ui_alien_encounter_score_row_" + row_number;
player setClientOmnvar( omnvar_title_name, row_title );
player setClientOmnvar( omnvar_score_name, row_score );
}
set_LUA_EoG_score_row( player, row_number, row_title, row_score )
{
omnvar_title_name = "ui_alien_eog_title_row_" + row_number;
omnvar_score_name = "ui_alien_eog_score_row_" + row_number;
player setClientOmnvar( omnvar_title_name, row_title );
player setClientOmnvar( omnvar_score_name, row_score );
}
make_wayPoint( shader, icon_width, icon_height, icon_alpha, location )
{
icon = NewHudElem();
icon SetShader( shader, icon_width, icon_height );
icon.alpha = icon_alpha;
icon SetWayPoint( true, true );
icon.x = location[0];
icon.y = location[1];
icon.z = location[2];
return icon;
}
///////////////////////////////////////////////////////
// Chaos HUD external interface
///////////////////////////////////////////////////////
chaos_HUD_init()
{
level.last_combo_meter_reset_time = 0;
}
set_combo_counter( value )
{
SetOmnvar( "ui_alien_chaos_combo_counter", value );
}
set_score_streak( value )
{
SetOmnvar( "ui_alien_chaos_score_streak", value );
}
set_total_score( value )
{
SetOmnvar( "ui_alien_chaos_total_score", value );
}
reset_combo_meter( combo_duration )
{
if ( is_combo_meter_reset_this_frame() )
return;
foreach( player in level.players )
{
now = gettime();
player SetClientOmnvar( "ui_alien_chaos_combo_meter_start", now );
player SetClientOmnvar( "ui_alien_chaos_combo_meter_end", now + int ( combo_duration * 1000 ) );
}
}
is_combo_meter_reset_this_frame()
{
current_time = getTime();
previous_time = level.last_combo_meter_reset_time;
level.last_combo_meter_reset_time = current_time;
return ( current_time == previous_time );
}
set_grace_period_clock( grace_period_end_time )
{
setOmnvar( "ui_alien_chaos_grace_period", grace_period_end_time );
}
unset_grace_period_clock()
{
setOmnvar( "ui_alien_chaos_grace_period", 0 );
}
set_has_combo_freeze( player, has_combo_freeze )
{
player setClientOmnvar( "ui_alien_chaos_has_meter_freeze", has_combo_freeze );
}
freeze_combo_meter( duration )
{
current_time = gettime();
SetOmnvar( "ui_alien_chaos_meter_freeze_start", current_time );
SetOmnvar( "ui_alien_chaos_meter_freeze_end", current_time + duration * 1000 );
}
unfreeze_combo_meter()
{
SetOmnvar( "ui_alien_chaos_meter_freeze_start", 0 );
SetOmnvar( "ui_alien_chaos_meter_freeze_end", 0 );
}
set_event_count( event_id, event_count )
{
foreach( player in level.players )
player SetClientOmnvar( "ui_alien_eog_score_row_" + event_id, event_count );
}
set_has_chaos_class_skill_bonus( player, class_index )
{
player setClientOmnvar( "ui_alien_chaos_class_skill_bonus", class_index );
}
unset_has_chaos_class_skill_bonus( player )
{
player setClientOmnvar( "ui_alien_chaos_class_skill_bonus", 0 );
}
set_last_stand_timer( player, duration )
{
player setClientOmnvar( "ui_laststand_end_milliseconds", gettime() + ( duration * 1000 ) );
}
clear_last_stand_timer( player )
{
player setClientOmnvar( "ui_laststand_end_milliseconds", 0 );
}
turn_on_drill_meter_HUD( drill_duration_sec )
{
// Make drill meter move
SetOmnvar( "ui_alien_drill_state", 1 );
// Set UI drill end time
drill_end_time_ms = int ( gettime() + drill_duration_sec * 1000 );
SetOmnvar ( "ui_alien_drill_start_milliseconds" , gettime() );
SetOmnvar( "ui_alien_drill_end_milliseconds", drill_end_time_ms );
}
update_drill_health( drill_health )
{
SetOmnvar( "ui_alien_drill_health_text", drill_health );
}

View File

@ -0,0 +1,209 @@
#include common_scripts\utility;
intro_sequence_precache()
{
flag_init( "intro_sequence_complete" );
switch( level.script )
{
case "mp_alien_town":
town_intro_precache();
break;
default:
break;
}
}
play_intro_sequence( player )
{
switch( level.script )
{
case "mp_alien_town":
level thread alien_town_intro( player );
break;
default:
break;
}
}
////////////////////////////////////////////////////////////
// mp_alien_town
////////////////////////////////////////////////////////////
town_intro_precache()
{
alien_town_intro_precache_props();
alien_town_intro_precache_characters();
}
#using_animtree("multiplayer");
alien_town_intro_precache_characters()
{
PrecacheMpAnim( "alien_town_intro_boss" );
PrecacheMpAnim( "alien_town_intro_pilot" );
}
#using_animtree("animated_props");
alien_town_intro_precache_props()
{
PrecacheMpAnim( "alien_town_intro_chopper" );
//PrecacheMpAnim( "alien_town_intro_chopper_idle" );
//PrecacheMpAnim( "alien_town_intro_chopper_leave" );
PrecacheMpAnim( "alien_town_intro_drill" );
}
alien_town_intro( player )
{
level waittill( "introscreen_over" );
CHOPPER_START_POSITION = ( 2830.455, -398.027, 707.026 ); //<TODO J.C.> Maybe mark this position in map with script struct?
// Thay way, we can eliminate the need for helibrush.
//CHOPPER_IDLE_LOOP_TIMES = 1;
//add helicopter collision
helibrush = GetEnt( "helicoptercoll", "targetname" );
heli = SpawnHelicopter( player, CHOPPER_START_POSITION, helibrush.angles + (0,180,0) , "nh90_alien_intro", "tag_origin_vehicle" );
assert( IsDefined( heli ) );
//spawn helicopter
IntroHeli = spawn("script_model", CHOPPER_START_POSITION );
IntroHeli.angles = helibrush.angles;
IntroHeli SetModel( "vehicle_nh90_interior2" );
thread sfx_intro_heli_takeoff(heli);
heli setmodel( "tag_origin_vehicle" );
level.intro_heli = IntroHeli;
//spawn and setup models
boss_model = spawn_model( "mp_body_us_rangers_assault_a_urban", IntroHeli, "TAG_GUY1", ( 0, 0, 0 ) );
boss_model SetModel( "mp_body_us_rangers_assault_a_urban" );
boss_head = spawn_model( "head_mp_head_a", boss_model, "J_spine4", ( 0, 0, 0 ) );
pilot_model = spawn_model( "mp_body_us_rangers_assault_a_urban", IntroHeli, "tag_driver", ( 0, 0, 0 ) );
pilot_head = spawn_model( "head_mp_head_a", pilot_model, "J_spine4", ( 0, 0, 0 ) );
drill_model = spawn_model( "mp_laser_drill", IntroHeli, "TAG_GUY1", ( 0, 0, 0 ) );
thread sfx_intro_npc_foley(boss_model);
//play helicopter intro animations
IntroHeli ScriptModelPlayAnimDeltaMotion("alien_town_intro_chopper");
pilot_model ScriptModelPlayAnim("alien_town_intro_pilot");
pilot_head ScriptModelPlayAnim("alien_town_intro_pilot");
boss_model ScriptModelPlayAnim("alien_town_intro_boss");
boss_head ScriptModelPlayAnim("alien_town_intro_boss");
drill_model ScriptModelPlayAnim("alien_town_intro_drill");
thread sfx_intro_heli_drop_drill(drill_model);
helibrush thread wait_to_delete();
wait( GetAnimLength( %alien_town_intro_drill ) );
drill_model ScriptModelClearAnim();
drill_model Delete();
level thread mp_alien_town_intro_drill_setup();
//<TODO J.C.> Waiting for final asset here. Will spawn the actual drill to match the end position of the drill anim.
//play helicopter loop anim
/*
for( i = 0; i < CHOPPER_IDLE_LOOP_TIMES; i++ )
{
IntroHeli ScriptModelPlayAnimDeltaMotion("alien_town_intro_chopper_idle");
wait( GetAnimLength( %alien_town_intro_chopper_idle ) );
}
*/
//play helicopter leaving anim
//IntroHeli ScriptModelPlayAnimDeltaMotion("alien_town_intro_chopper_leave");
level thread kill_heli ( heli );
wait( GetAnimLength( %alien_town_intro_chopper) );
//clear the anim before deletion
pilot_model ScriptModelClearAnim();
pilot_head ScriptModelClearAnim();
boss_model ScriptModelClearAnim();
boss_head ScriptModelClearAnim();
IntroHeli ScriptModelClearAnim();
//clean up
boss_model Delete();
boss_head Delete();
pilot_model Delete();
pilot_head Delete();
IntroHeli Delete();
}
wait_to_delete()
{
level endon( "game_ended" );
CONST_HELI_COLLISION_DELETE_TIME = 16.5; // wait for heli to leave the ground high enough
wait ( CONST_HELI_COLLISION_DELETE_TIME );
self delete();
}
kill_heli ( heli )
{
wait ( 10 );
heli Vehicle_SetSpeed( 50,10 );
heli SetVehGoalPos ( heli.origin + (0,0,1600 ));
wait ( 10 );
heli delete();
}
spawn_model( model_name, attach_to_entity, tag_name, spawn_angle_offset )
{
new_model = spawn( "script_model", ( 0, 0, 0 ) );
new_model SetModel( model_name );
new_model.origin = attach_to_entity GetTagOrigin( tag_name );
new_model.angles = attach_to_entity GetTagAngles( tag_name ) + spawn_angle_offset;
new_model LinkTo( attach_to_entity, tag_name );
return new_model;
}
intro_sequence_enabled()
{
/#
if ( maps\mp\alien\_debug::StartPointEnabled() )
return false;
#/
if ( maps\mp\alien\_utility::is_chaos_mode() )
return false;
return ( getDvarInt( "scr_alien_intro", 1 ) == 1 );
}
mp_alien_town_intro_drill_setup()
{
level.initial_drill_origin = ( 2834.272, -243.002, 524.068 );
level.initial_drill_angles = ( 0.995, -103.877, 1.287 );
level notify ( "spawn_intro_drill" );
wait( 8 );
flag_set( "intro_sequence_complete" );
}
sfx_intro_heli_takeoff(heli)
{
heli Vehicle_TurnEngineOff();
heli PlaySound("alien_heli_intro_takeoff");
}
sfx_intro_heli_drop_drill(drill)
{
//wait 8;
wait( GetAnimLength( %alien_town_intro_drill ) - 0.5);
//IPrintLnBold("Drill");
drill PlaySound("alien_heli_drill_drop");
}
sfx_intro_npc_foley(npc)
{
wait 2.53;
npc PlaySound("alien_heli_npc_foley");
}

View File

@ -0,0 +1,351 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
CONST_SOFLAM_AMMO = 3;
init()
{
level.lasedStrikeGlow = loadfx("fx/misc/laser_glow");
level.lasedStrikeExplode = LoadFX( "fx/explosions/uav_advanced_death" );
thread onPlayerConnect();
}
onPlayerConnect()
{
for(;;)
{
level waittill("connected", player);
player thread onPlayerSpawned();
player.soflamAmmoUsed = 0;
}
}
onPlayerSpawned()
{
self endon("disconnect");
for(;;)
{
self waittill( "spawned_player" );
self thread watch_alien_soflam_usage();
self thread watch_alien_soflam_weaponswitch();
}
}
watch_alien_soflam_weaponswitch()
{
self endon( "disconnect" );
self endon("death");
while ( 1 )
{
self waittill( "weapon_change",newWeapon );
if ( newWeapon == "aliensoflam_mp" )
self SetWeaponAmmoClip ( "aliensoflam_mp", CONST_SOFLAM_AMMO - self.soflamAmmoUsed );
}
}
watch_alien_soflam_usage()
{
self notify( "watchaliensoflamusage" );
self endon( "watchaliensoflamusage" );
level endon( "game_ended" );
self endon( "disconnect" );
while( self isChangingWeapon() )
wait ( 0.05 );
for(;;)
{
if ( self AttackButtonPressed() && self GetCurrentWeapon() == "aliensoflam_mp" && self AdsButtonPressed() && !self IsUsingTurret() )
{
//self WeaponLockNoClearance( false );
self WeaponLockTargetTooClose( false );
self WeaponLockFree();
targetInfo = getTargetPoint();
if( !isDefined( targetInfo ) )
{
wait 0.05;
continue;
}
if( !isDefined( targetInfo[0] ) )
{
wait 0.05;
continue;
}
targPoint = targetInfo[0];
self attackLasedTarget( targPoint );
}
wait( 0.05 );
}
}
playLockSound()
{
if ( isDefined( self.playingLockSound ) && self.playingLockSound )
return;
self PlayLocalSound( "javelin_clu_lock" );
self.playingLockSound = true;
wait( .75 );
self StopLocalSound( "javelin_clu_lock" );
self.playingLockSound = false;
}
playLockErrorSound()
{
if ( isDefined( self.playingLockSound ) && self.playingLockSound )
return;
self PlayLocalSound( "javelin_clu_aquiring_lock" );
self.playingLockSound = true;
wait( .75 );
self StopLocalSound( "javelin_clu_aquiring_lock" );
self.playingLockSound = false;
}
attackLasedTarget( targPoint )
{
finalTargetEnt = undefined;
midTargetEnt = undefined;
upQuantity = 6000;
upVector = (0, 0, upQuantity );
backDist = 3000;
forward = AnglesToForward( self.angles );
ownerOrigin = self.origin;
startpos = ownerOrigin + upVector + forward * backDist * -1;
foundAngle = false;
//straight down
skyTrace = bulletTrace( targPoint + (0,0,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (0,0,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (0,0,upQuantity), 25, (1,0,0) );
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (300,0,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (300,0,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (300,0,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (0,300,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (0,300,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (0,300,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (0,-300,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (0,-300,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (0,-300,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (300,300,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (300,300,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (300,300,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (-300,0,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (-300,0,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (-300,0,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (-300,-300,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (-300,-300,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (-300,-300,upQuantity), 25, (1,0,0) );
}
if( !foundAngle )
{
skyTrace = bulletTrace( targPoint + (300,-300,upQuantity), targPoint , false );
if( skyTrace["fraction"] > .99 )
{
foundAngle = true;
startPos = targPoint + (300,-300,upQuantity);
}
//self thread drawLine( targPoint, targPoint + (300,-300,upQuantity), 25, (1,0,0) );
}
//backwards vector from player over target area
if( !foundAngle )
{
for ( i = 0; i < 5; i++ )
{
upQuantity = upQuantity / 2;
upVector = (0, 0, upQuantity );
startpos = self.origin + upVector + forward * backDist * -1;
targetSkyCheck = BulletTrace( targPoint, startpos, false );
if ( targetSkyCheck["fraction"] > .99 )
{
foundAngle = true;
break;
}
wait( 0.05 );
}
}
//check increased angle to try to get it over large objects
if( !foundAngle )
{
for ( i = 0; i < 5; i++ )
{
upQuantity = upQuantity * 2.5;
upVector = (0, 0, upQuantity );
startpos = self.origin + upVector + forward * backDist * -1;
targetSkyCheck = BulletTrace( targPoint, startpos, false );
if ( targetSkyCheck["fraction"] > .99 )
{
foundAngle = true;
break;
}
wait( 0.05 );
}
}
if( !foundAngle )
{
self thread cantHitTarget();
return false;
}
//finalTargetEnt = Spawn( "script_origin", targPoint );
finalTargetEnt = SpawnFx( level.lasedStrikeGlow, targPoint );
self thread playLockSound();
self WeaponLockFinalize( targPoint, (0,0,0), false );
self thread update_soflam_ammocount();
missile = MagicBullet("aliensoflam_missle_mp", startPos, targPoint, self);
missile Missile_SetTargetEnt( finalTargetEnt );
self thread loopTriggeredeffect( finalTargetEnt, missile );
self WeaponLockFree();
missile waittill( "death" );
if( isDefined( finalTargetEnt ) )
{
finalTargetEnt delete();
}
Earthquake(.4,1,targPoint,850 );
return true;
}
loopTriggeredEffect( effect, missile )
{
missile endon( "death" );
level endon( "game_ended" );
for( ;; )
{
TriggerFX( effect );
wait ( 0.5 );
}
}
cantHitTarget()
{
self thread playLockErrorSound();
//self WeaponLockNoClearance( true );
self WeaponLockTargetTooClose( true );
}
getTargetPoint()
{
origin = self GetEye();
angles = self GetPlayerAngles();
forward = AnglesToForward( angles );
endpoint = origin + forward * 15000;
res = BulletTrace( origin, endpoint, false, undefined );
if ( res["surfacetype"] == "none" )
return undefined;
if ( res["surfacetype"] == "default" )
return undefined;
results = [];
results[0] = res["position"];
results[1] = res["normal"];
return results;
}
update_soflam_ammocount()
{
self.soflamAmmoUsed++;
self SetWeaponAmmoClip ( "aliensoflam_mp", CONST_SOFLAM_AMMO - self.soflamAmmoUsed );
if( self.soflamAmmoUsed >= CONST_SOFLAM_AMMO )
{
self.soflamAmmoUsed = 0;
self takeweapon( "aliensoflam_mp" );
if ( !maps\mp\alien\_utility::is_true( self.has_special_weapon ) && !maps\mp\alien\_utility::is_true( self.is_holding_deployable ) )
self SwitchToWeapon( self GetWeaponsListPrimaries()[0] );
}
}

1039
maps/mp/alien/_laststand.gsc Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

291
maps/mp/alien/_nuke.gsc Normal file
View File

@ -0,0 +1,291 @@
#include common_scripts\utility;
#include maps\mp\_utility;
// the nuke ended the game in MW2, for MW3 it will be an MOAB, not end the game but kill the other team and emp them for 60 seconds, it will also change the visionset for the level
init()
{
level.nukeVisionSet = "alien_nuke";
level.nukeVisionSetFailed = "alien_nuke_blast";
if ( level.script == "mp_alien_last" )
{
level._effect[ "nuke_flash" ] = loadfx( "vfx/moments/alien/player_nuke_flash_alien_last" );
}
else
{
level._effect[ "nuke_flash" ] = loadfx( "fx/explosions/player_death_nuke_flash_alien" );
}
SetDvarIfUninitialized( "scr_nukeTimer", 10 );
SetDvarIfUninitialized( "scr_nukeCancelMode", 0 );
level.nukeTimer = getDvarInt( "scr_nukeTimer" );
level.cancelMode = getDvarInt( "scr_nukeCancelMode" );
level.nukeInfo = spawnStruct();
level.nukeInfo.xpScalar = 2;
level.nukeDetonated = undefined;
level thread onPlayerConnect();
}
delaythread_nuke( delay, func )
{
level endon ( "nuke_cancelled" );
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( delay );
thread [[ func ]]();
}
// used in aliens mode
doNukeSimple()
{
level.nukeInfo.player = self;
level.nukeInfo.team = self.pers["team"];
level.nukeIncoming = true;
level thread delaythread_nuke( (level.nukeTimer - 3.3), ::nukeSoundIncoming );
level thread delaythread_nuke( level.nukeTimer, ::nukeSoundExplosion );
level thread delaythread_nuke( level.nukeTimer, ::nukeSlowMo );
level thread delaythread_nuke( level.nukeTimer, ::nukeEffects );
level thread delaythread_nuke( (level.nukeTimer + 0.25), ::nukeVision );
level thread delaythread_nuke( (level.nukeTimer + 1.5), ::nukeDeath );
//level thread delaythread_nuke( (level.nukeTimer + 1.5), ::nukeEarthquake );
// need objects to play sound off of, i'm keeping them on level so we don't spawn them more than once if multiple nukes get called in a match
if( !IsDefined( level.nuke_soundObject ) )
{
level.nuke_soundObject = Spawn( "script_origin", (0,0,1) );
level.nuke_soundObject hide();
}
}
nukeDeath()
{
level notify( "nuke_death" );
}
nukeSoundIncoming()
{
level endon ( "nuke_cancelled" );
if( IsDefined( level.nuke_soundObject ) )
level.nuke_soundObject PlaySound( "nuke_incoming" );
}
nukeSoundExplosion()
{
level endon ( "nuke_cancelled" );
if( IsDefined( level.nuke_soundObject ) )
{
level.nuke_soundObject PlaySound( "nuke_explosion" );
level.nuke_soundObject PlaySound( "nuke_wave" );
}
}
nukeEffects()
{
level endon ( "nuke_cancelled" );
level.nukeDetonated = true;
foreach( player in level.players )
{
playerForward = anglestoforward( player.angles );
playerForward = ( playerForward[0], playerForward[1], 0 );
playerForward = VectorNormalize( playerForward );
nukeDistance = 5000;
nukeLoc = player.origin + ( playerForward * nukeDistance );
// nuke location override: from aliens
if ( isdefined( level.nukeLoc ) )
nukeLoc = level.nukeLoc;
nukeAngles = ( 0, (player.angles[1] + 180), 90 );
// nuke angle override: from aliens
if ( IsDefined( level.nukeAngles ) )
nukeAngles = level.nukeAngles;
nukeEnt = Spawn( "script_model", nukeLoc );
nukeEnt setModel( "tag_origin" );
nukeEnt.angles = nukeAngles;
nukeEnt thread nukeEffect( player );
}
}
nukeEffect( player )
{
level endon ( "nuke_cancelled" );
player endon( "disconnect" );
waitframe();
PlayFXOnTagForClients( level._effect[ "nuke_flash" ], self, "tag_origin", player );
}
nukeSlowMo()
{
level endon ( "nuke_cancelled" );
//SetSlowMotion( <startTimescale>, <endTimescale>, <deltaTime> )
SetSlowMotion( 1.0, 0.25, 0.5 );
level waittill( "nuke_death" );
SetSlowMotion( 0.25, 1, 2.0 );
}
nukeVision()
{
level endon ( "nuke_cancelled" );
level.nukeVisionInProgress = true;
// level waittill( "nuke_death" );
transition_time = 0.75;
foreach ( player in level.players )
{
// if spectating player is spectating someone who escaped
if ( isdefined( player.sessionstate ) && player.sessionstate == "spectator" )
{
spectated_player = player GetSpectatingPlayer();
if ( isdefined( spectated_player ) )
{
// go with what spectated player is using
if ( ( isdefined( spectated_player.nuke_escaped ) && spectated_player.nuke_escaped ) )
player set_vision_for_nuke_escaped( transition_time );
else
player set_vision_for_nuke_failed( transition_time );
}
else
{
// use failed vision if player isnt spectating anyone, meaning he could be looking at nuke from bad angle
player set_vision_for_nuke_failed( transition_time );
}
}
else
{
if ( ( isdefined( player.nuke_escaped ) && player.nuke_escaped ) )
player set_vision_for_nuke_escaped( transition_time );
else
player set_vision_for_nuke_failed( transition_time );
}
}
fog_nuke(transition_time);
// restore_fog( 0 );
// VisionSetPain( level.nukeVisionSet );
}
// Julian - Kyle, you may use the following functions to replace vision change with your fx
set_vision_for_nuke_escaped( transition_time )
{
self VisionSetNakedForPlayer( level.nukeVisionSet, transition_time );
self VisionSetPainForPlayer( level.nukeVisionSet );
}
set_vision_for_nuke_failed( transition_time )
{
PlayFXOnTagForClients( level._effect[ "vfx/moments/alien/nuke_fail_screen_flash" ], self, "tag_eye",self);
self VisionSetNakedForPlayer( level.nukeVisionSetFailed, transition_time );
self VisionSetPainForPlayer( level.nukeVisionSetFailed );
}
fog_nuke(transition_time)
{
if ( !isdefined( level.nuke_fog_setting ) )
return;
ent = level.nuke_fog_setting;
SetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.sunRed,
ent.sunGreen,
ent.sunBlue,
ent.HDRSunColorIntensity,
ent.sunDir,
ent.sunBeginFadeAngle,
ent.sunEndFadeAngle,
ent.normalFogScale,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
restore_fog( transition_time )
{
if ( !isdefined( level.restore_fog_setting ) )
return;
ent = level.restore_fog_setting;
SetExpFog(
ent.startDist,
ent.halfwayDist,
ent.red,
ent.green,
ent.blue,
ent.HDRColorIntensity,
ent.maxOpacity,
transition_time,
ent.sunRed,
ent.sunGreen,
ent.sunBlue,
ent.HDRSunColorIntensity,
ent.sunDir,
ent.sunBeginFadeAngle,
ent.sunEndFadeAngle,
ent.normalFogScale,
ent.skyFogIntensity,
ent.skyFogMinAngle,
ent.skyFogMaxAngle );
}
nukeEarthquake()
{
level endon ( "nuke_cancelled" );
level waittill( "nuke_death" );
// TODO: need to get a different position to call this on
//earthquake( 0.6, 10, nukepos, 100000 );
//foreach( player in level.players )
//player PlayRumbleOnEntity( "damage_heavy" );
}
onPlayerConnect()
{
for(;;)
{
level waittill("connected", player);
player thread onPlayerSpawned();
}
}
onPlayerSpawned()
{
self endon("disconnect");
for(;;)
{
self waittill( "spawned_player" );
// make sure the vision set stays on between deaths
if( IsDefined( level.nukeDetonated ) )
self VisionSetNakedForPlayer( level.nukeVisionSet, 0 );
}
}

View File

@ -0,0 +1,577 @@
#include maps\mp\alien\_utility;
#include common_scripts\utility;
/*
* Outline color index:
* 0 - white
* 1 - red
* 2 - green
* 3 - cyan
* 4 - orange
* 5 - yellow
* 7 - magenta
*/
CONST_MIN_PLAYER_OUTLINE_ENABLE_DIST_SQUARED = 2250000; // 1500 * 1500
CONST_MAX_ITEM_OUTLINE_ENABLE_DIST_SQUARED = 122500; // 350 * 350
CONST_MAX_PILLAGE_OUTLINE_ENABLE_DIST_SQUARED = 27225; // 165 * 165
CONST_MAX_WEAPON_OUTLINE_ENABLE_DIST_SQUARED = 1000000; // 1000 * 1000
CONST_MAX_DRILL_OUTLINE_ENABLE_DIST_SQUARED = 1000000; // 1000 * 1000
PLAYER_COLOR_INDEX_BOOSTED_HEALTH = 0;
PLAYER_COLOR_INDEX_GOOD_HEALTH = 3;
PLAYER_COLOR_INDEX_OKAY_HEALTH = 5;
PLAYER_COLOR_INDEX_BAD_HEALTH = 4;
ITEM_COLOR_INDEX_ENOUGH_MONEY = 3;
ITEM_COLOR_INDEX_NOT_ENOUGH_MONEY = 4;
CONST_HEALTH_INVULNERABLE = 20000;
CONST_OUTLINE_COLOR_RED = 4;
CONST_OUTLINE_COLOR_GREEN = 3;
CONST_OUTLINE_COLOR_NONE = 0;
outline_init()
{
level.outline_watch_list = [];
level.outline_pillage_watch_list = [];
level.outline_weapon_watch_list = [];
level.outline_drill_watch_list = [];
level.outline_hive_watch_list = [];
level.outline_drill_preplant_watch_list = [];
}
outline_monitor()
{
self endon ( "disconnect" );
level endon ( "game_ended" );
self waittill ( "spawned" );
self childthread outline_monitor_think();
}
outline_monitor_think()
{
while ( true )
{
prof_begin( "outline_monitor" );
self player_outline();
waitframe();
self item_outline();
waitframe();
self item_outline_pillage();
waitframe();
self intel_outline();
waitframe();
self item_outline_weapon_monitor();
waitframe();
self item_outline_drill_monitor();
waitframe();
self hive_outline_monitor();
waitframe();
self drill_preplant_outline_monitor();
waitframe();
prof_end( "outline_monitor" );
}
}
update_drill_outline()
{
level waittill_any_timeout( 1, "drill_spawned" );
foreach ( player in level.players )
{
outline_color = player get_item_outline_color( level.drill );
if ( outline_color == CONST_OUTLINE_COLOR_GREEN || outline_color == CONST_OUTLINE_COLOR_RED )
enable_outline_for_player( level.drill, player, outline_color, false, "high" );
else
disable_outline_for_player( level.drill, player );
}
}
player_outline()
{
self endon( "refresh_outline" );
foreach ( player in level.players )
{
if ( self == player )
continue;
if ( should_put_player_outline_on ( player ) )
enable_outline_for_player( player, self, get_color_index_player ( player ), false, "high" );
else
disable_outline_for_player( player, self );
}
}
set_alien_outline()
{
self endon( "unset_adrenaline" );
self endon( "switchblade_over" );
self endon ( "disconnect" );
self endon( "death" );
level endon ( "game_ended" );
while ( true )
{
foreach ( alien in maps\mp\alien\_spawnlogic::get_alive_enemies() )
{
if(isdefined(level.kraken) && alien == level.kraken)
continue;
if(IsDefined(alien.agent_type) && alien.agent_type == "kraken_tentacle")
continue;
if ( isDefined( alien.damaged_by_players ) ) // this is set by a challenge that uses outlines, so don't mess with the outlines for these guys
continue;
if ( isDefined( alien.marked_for_challenge ) ) // this is set by a challenge that uses outlines, so don't mess with the outlines for these guys
continue;
if ( isDefined( alien.pet) )
continue;
else
{
if( !isdefined( alien.no_outline_on_alien ) )
{
if( IsDefined( alien.feral_occludes ) )
{
enable_outline_for_player( alien, self, 4, true, "high" );
}
else
{
enable_outline_for_player( alien, self, 4, false, "high" );
}
}
}
}
wait ( 0.5 );
}
}
unset_alien_outline()
{
foreach ( alien in maps\mp\alien\_spawnlogic::get_alive_enemies() )
{
if ( isDefined( alien.damaged_by_players ) ) // this is set by a challenge that uses outlines, so don't mess with the outlines for these guys
continue;
if ( isDefined( alien.marked_for_challenge ) ) // this is set by a challenge that uses outlines, so don't mess with the outlines for these guys
continue;
if ( !isDefined( alien.pet) )
disable_outline_for_player( alien, self );
}
}
hive_outline_monitor()
{
self endon( "refresh_outline" );
foreach (index, item in level.outline_hive_watch_list )
{
enable_outline_for_player( item, self, 4, true, "medium" );
if ( index%10 == 0 )
waitframe();
}
}
drill_preplant_outline_monitor()
{
self endon( "refresh_outline" );
foreach ( index, item in level.outline_drill_preplant_watch_list )
{
if ( !isdefined ( item ) )
continue;
if( should_put_drill_outline_on ( item ) )
enable_outline_for_player( item, self, 3, false, "high" );
else
disable_outline_for_player( item, self );
if( index%6 == 0 )
waitframe();
}
}
item_outline()
{
self endon( "refresh_outline" );
foreach (index, item in level.outline_watch_list )
{
if ( !isDefined ( item ) )
continue;
outline_color = get_item_outline_color( item );
if ( outline_color == CONST_OUTLINE_COLOR_GREEN )
enable_outline_for_player( item, self, get_color_index_item ( item ), true, "low" );
else if ( outline_color == CONST_OUTLINE_COLOR_RED ) //player is holding an item and cant' search this spot
enable_outline_for_player( item, self, 4, true, "low" );
else
disable_outline_for_player( item, self );
if( index%6 == 0 )
waitframe();
}
}
item_outline_pillage()
{
self endon( "refresh_outline" );
foreach (index, item in level.outline_pillage_watch_list )
{
if ( !isDefined ( item ) )
continue;
outline_color = get_pillage_item_outline_color( item );
if ( outline_color == CONST_OUTLINE_COLOR_GREEN )
enable_outline_for_player( item, self, 3, false, "low" );
else if ( outline_color == CONST_OUTLINE_COLOR_RED ) //player is holding an item and cant' search this spot
enable_outline_for_player( item, self, CONST_OUTLINE_COLOR_RED, false, "low" );
else
disable_outline_for_player( item, self );
if ( index%10 == 0 )
waitframe();
}
}
intel_outline()
{
if(IsDefined(level.intel_outline_func))
[[level.intel_outline_func]]();
}
item_outline_weapon_monitor()
{
self endon( "refresh_outline" );
foreach ( index, item in level.outline_weapon_watch_list )
{
if ( !isdefined ( item ) )
continue;
weapon_flag = true;
outline_color = get_weapon_outline_color( item );
if ( outline_color == CONST_OUTLINE_COLOR_GREEN )
enable_outline_for_player( item, self, get_color_index_item ( item, weapon_flag ), true, "low" );
else if ( outline_color == CONST_OUTLINE_COLOR_RED ) //player is holding an item and cant' buy a weapon
enable_outline_for_player( item, self, 4, true, "low" );
else
disable_outline_for_player( item, self );
if( index%6 == 0 )
waitframe();
}
}
item_outline_drill_monitor()
{
if( isDefined( level.item_outline_drill_monitor_override ) )
{
[[level.item_outline_drill_monitor_override]]();
return;
}
self endon( "refresh_outline" );
last_used_index = undefined;
foreach ( drill in level.outline_drill_watch_list )
{
ratio = ( level.drill.health - CONST_HEALTH_INVULNERABLE ) / (level.drill.maxhealth - CONST_HEALTH_INVULNERABLE );
if ( ratio < 0.75 )
{
if ( should_put_drill_outline_on( drill ) )
enable_outline_for_player( drill, self, get_drill_widget_color ( drill ), false, "high" );
else
disable_outline_for_player( drill, self );
}
else
disable_outline_for_player( drill, self );
if ( isDefined( level.drill) && drill == level.drill )
{
index = get_drill_widget_color ( drill );
if ( isDefined ( last_used_index ) && last_used_index == index ) //don't spam the omnvar
continue;
last_used_index = index;
}
}
}
get_drill_widget_color( drill )
{
ratio = ( level.drill.health - CONST_HEALTH_INVULNERABLE ) / (level.drill.maxhealth - CONST_HEALTH_INVULNERABLE );
if ( ratio <= 0.30 )
return PLAYER_COLOR_INDEX_BAD_HEALTH;
else if ( ratio <= 0.75 )
return PLAYER_COLOR_INDEX_OKAY_HEALTH;
else if ( ratio <= 1 )
return PLAYER_COLOR_INDEX_GOOD_HEALTH;
else
return PLAYER_COLOR_INDEX_BOOSTED_HEALTH;
}
get_color_index_item ( item, weapon_flag )
{
if ( self has_pistols_only_relic_and_no_deployables() && is_true( weapon_flag ) )
cost = level.pistol_ammo_cost;
else
cost = item.cost;
if ( maps\mp\alien\_persistence::player_has_enough_currency( cost ) || is_true ( item.enabled ) )
return ITEM_COLOR_INDEX_ENOUGH_MONEY;
else
return ITEM_COLOR_INDEX_NOT_ENOUGH_MONEY;
}
get_color_index_player( player )
{
health_ratio = player.health / 100;
if ( health_ratio <= 0.33 || player.inlaststand )
return PLAYER_COLOR_INDEX_BAD_HEALTH;
else if ( health_ratio <= 0.66 )
return PLAYER_COLOR_INDEX_OKAY_HEALTH;
else if ( health_ratio <= 1.0 )
return PLAYER_COLOR_INDEX_GOOD_HEALTH;
else
return PLAYER_COLOR_INDEX_BOOSTED_HEALTH;
}
get_item_outline_color ( item )
{
if ( isDefined ( item.classname ) && item.classname == "misc_turret" && isDefined( item.owner ) )
{
return CONST_OUTLINE_COLOR_NONE;
}
in_close_proximity = distanceSquared ( self.origin, item.origin ) < CONST_MAX_ITEM_OUTLINE_ENABLE_DIST_SQUARED;
if ( !in_close_proximity )
return CONST_OUTLINE_COLOR_NONE;
if ( self has_special_weapon() )
{
if( isDefined ( item.targetname ) && ( item.targetname == "fire_trap_barrel" || item.targetname == "puddle_generator" || item.targetname == "fence_generator" ) )
return CONST_OUTLINE_COLOR_GREEN;
else if ( isDefined ( item.classname ) && item.classname == "misc_turret" )
return CONST_OUTLINE_COLOR_GREEN;
else
return CONST_OUTLINE_COLOR_RED;
}
else if ( self is_holding_deployable() )
{
return CONST_OUTLINE_COLOR_RED;
}
return CONST_OUTLINE_COLOR_GREEN;
}
get_pillage_item_outline_color ( item )
{
if ( !isdefined( item ) )
{
return CONST_OUTLINE_COLOR_NONE;
}
in_close_proximity = distanceSquared ( self.origin, item.origin ) < CONST_MAX_PILLAGE_OUTLINE_ENABLE_DIST_SQUARED;
if ( !in_close_proximity )
return CONST_OUTLINE_COLOR_NONE;
if(IsDefined(item.is_locker) && item.is_locker && !IsDefined(self.locker_key))
return CONST_OUTLINE_COLOR_NONE;
if ( self is_holding_deployable() || self has_special_weapon() )
{
return CONST_OUTLINE_COLOR_RED;
}
return CONST_OUTLINE_COLOR_GREEN;
}
get_weapon_outline_color ( item )
{
in_close_proximity = distanceSquared ( self.origin, item.origin ) < CONST_MAX_WEAPON_OUTLINE_ENABLE_DIST_SQUARED;
if ( !in_close_proximity )
return CONST_OUTLINE_COLOR_NONE;
if ( is_chaos_mode() && maps\mp\alien\_chaos::is_weapon_recently_picked_up( self, item.weapon_ref ) )
return CONST_OUTLINE_COLOR_RED;
if( self is_holding_deployable() )
{
return CONST_OUTLINE_COLOR_RED;
}
if ( !is_true ( item.is_recipe_table) && self maps\mp\alien\_prestige::prestige_getPistolsOnly() == 1 && !self maps\mp\alien\_prestige::prestige_getNoDeployables() == 1 )
{
return CONST_OUTLINE_COLOR_RED;
}
if ( isDefined( level.get_custom_weapon_outline_func ) && [[ level.get_custom_weapon_outline_func ]]( item ) )
{
return CONST_OUTLINE_COLOR_RED;
}
if ( self has_special_weapon() && !is_true ( item.is_recipe_table ))
{
if( isDefined ( level.drill) && item == level.drill )
return CONST_OUTLINE_COLOR_GREEN;
else
return CONST_OUTLINE_COLOR_RED;
}
return CONST_OUTLINE_COLOR_GREEN;
}
should_put_drill_outline_on ( item )
{
in_close_proximity = distanceSquared ( self.origin, item.origin ) < CONST_MAX_WEAPON_OUTLINE_ENABLE_DIST_SQUARED;
if ( !in_close_proximity )
return false;
return true;
}
should_put_player_outline_on ( player )
{
if ( !isAlive ( player ) || !isDefined ( player.maxhealth ) || !player.maxhealth )
return false;
not_close_proximity = distanceSquared ( self.origin, player.origin ) > CONST_MIN_PLAYER_OUTLINE_ENABLE_DIST_SQUARED;
if ( not_close_proximity )
return true;
not_in_LOS = !BulletTracePassed ( self getEye(), player getEye(), false, self );
return ( not_in_LOS );
}
add_to_outline_watch_list ( item, cost )
{
item.cost = cost;
level.outline_watch_list [ level.outline_watch_list.size ] = item;
}
remove_from_outline_watch_list ( item )
{
level.outline_watch_list = common_scripts\utility::array_remove( level.outline_watch_list, item );
thread remove_outline( item );
}
add_to_drill_preplant_watch_list ( item )
{
level.outline_drill_preplant_watch_list [ level.outline_drill_preplant_watch_list.size ] = item;
}
remove_from_drill_preplant_watch_list ( item )
{
level.outline_drill_preplant_watch_list = common_scripts\utility::array_remove( level.outline_drill_preplant_watch_list, item );
thread remove_outline( item );
}
add_to_outline_hive_watch_list ( item )
{
level.outline_hive_watch_list [ level.outline_hive_watch_list.size ] = item;
}
remove_from_outline_hive_watch_list ( item )
{
level.outline_hive_watch_list = common_scripts\utility::array_remove( level.outline_hive_watch_list, item );
thread remove_outline( item );
}
add_to_outline_pillage_watch_list ( item, cost )
{
if ( !array_contains(level.outline_pillage_watch_list, item ) )
{
item.cost = cost;
level.outline_pillage_watch_list [ level.outline_pillage_watch_list.size ] = item;
}
}
remove_from_outline_pillage_watch_list ( item )
{
level.outline_pillage_watch_list = common_scripts\utility::array_remove( level.outline_pillage_watch_list, item );
thread remove_outline( item );
}
add_to_outline_weapon_watch_list ( item, cost )
{
item.cost = cost;
level.outline_weapon_watch_list [ level.outline_weapon_watch_list.size ] = item;
}
remove_from_outline_weapon_watch_list ( item )
{
level.outline_weapon_watch_list = common_scripts\utility::array_remove( level.outline_weapon_watch_list, item );
thread remove_outline( item );
}
add_to_outline_drill_watch_list ( item, cost )
{
item.cost = cost;
level.outline_drill_watch_list [ level.outline_drill_watch_list.size ] = item;
}
remove_from_outline_drill_watch_list ( item )
{
level.outline_drill_watch_list = common_scripts\utility::array_remove( level.outline_drill_watch_list, item );
thread remove_outline( item );
}
remove_outline( item )
{
if ( !isdefined( item ) )
return;
foreach( player in level.players )
{
if ( isdefined( player ) )
{
player notify( "refresh_outline" );
disable_outline_for_player( item, player );
}
}
}
enable_outline_for_players( item, players, color_index, depth_enable, priority )
{
item HudOutlineEnableForClients( players, color_index, depth_enable );
}
enable_outline_for_player( item, player, color_index, depth_enable, priority )
{
item HudOutlineEnableForClient( player, color_index, depth_enable );
}
disable_outline_for_players( item, players )
{
item HudOutlineDisableForClients( players );
}
disable_outline_for_player( item, player )
{
item HudOutlineDisableForClient( player );
}
enable_outline( item, color_index, depth_enable )
{
item HudOutlineEnable( color_index, depth_enable );
}
disable_outline( item )
{
item HudOutlineDisable();
}
outline_proto_enabled() { return ( GetDvarInt ( "enable_outline_proto" ) == 1 ); }
is_host( player ) { return player isHost(); }

View File

@ -0,0 +1,95 @@
#include maps\mp\alien\_perkfunctions;
//////////////////////////////////////////////////////////////////////////////////////////
// This file contains perk interface function for other components of the game mode //
//////////////////////////////////////////////////////////////////////////////////////////
init_each_perk()
{
self.perk_data = [];
self.perk_data[ "health" ] = init_perk_health();
self.perk_data[ "damagemod" ] = init_perk_bullet_damage();
self.perk_data[ "medic" ] = init_perk_medic();
self.perk_data[ "rigger" ] = init_perk_rigger();
self.perk_data[ "pistol" ] = init_perk_pistol();
self.perk_data[ "none" ] = init_perk_none();
}
// === perk_health ===
perk_GetMeleeScalar() { return self.perk_data[ "health" ].melee_scalar; }
perk_GetMaxHealth() { return self.perk_data[ "health" ].max_health; }
// === perk_bullet_damage ===
perk_GetBulletDamageScalar() { return self.perk_data[ "damagemod" ].bullet_damage_scalar; }
// === perk_medic ===
perk_GetReviveTimeScalar() { return self.perk_data[ "medic" ].revive_time_scalar; }
perk_GetGasDamageScalar() { return self.perk_data[ "medic" ].gas_damage_scalar; }
perk_GetMoveSpeedScalar() { return self.perk_data[ "medic" ].move_speed_scalar; }
perk_GetReviveDamageScalar() { return self.perk_data[ "medic" ].revive_damage_scalar; }
// === perk_rigger ===
perk_GetDrillHealthScalar() { return self.perk_data[ "rigger" ].drill_health_scalar; }
perk_GetDrillTimeScalar() { return self.perk_data[ "rigger" ].drill_time_scalar; }
perk_GetTrapCostScalar() { return self.perk_data[ "rigger" ].trap_cost_scalar; }
perk_GetTrapDamageScalar() { return self.perk_data[ "rigger" ].trap_damage_scalar; }
perk_GetTrapDurationScalar() { return self.perk_data[ "rigger" ].trap_duration_scalar; }
perk_GetCurrencyScalePerHive() { return self.perk_data[ "rigger" ].currency_scale_per_hive; }
perk_GetExplosiveDamageScalar() { return self.perk_data[ "rigger" ].explosive_damage_scalar; }
perk_GetRepairDamageScalar() { return self.perk_data[ "rigger" ].repair_damage_scalar; }
// === perk_pistol ===
perk_GetPistolRegen() { return self.perk_data[ "pistol" ].pistol_regen; }
perk_GetPistolOverkill() { return self.perk_data[ "pistol" ].pistol_overkill; }
/*
=============
///ScriptDocBegin
"Name: has_perk( <required> perk name, <optional> perk level list )"
"Summary: Returns true if the player has the specified perk (at one of the specified level) at either Perk 0 slot or Perk 1 slot"
"Module: Alien"
"Example: if ( player has_perk( "perk_medic", [3, 4] )"
"SPMP: multiplayer"
///ScriptDocEnd
=============
*/
has_perk( perk_name, perk_level_list )
{
AssertEx( is_valid_perk( perk_name ), perk_name + " is not a valid perk." );
selected_perk_0 = maps\mp\alien\_persistence::get_selected_perk_0();
perk_0_level = maps\mp\alien\_persistence::get_perk_0_level();
selected_perk_1 = maps\mp\alien\_persistence::get_selected_perk_1();
perk_1_level = maps\mp\alien\_persistence::get_perk_1_level();
selected_perk_0_secondary = "perk_none";
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "multi_class" ))
{
selected_perk_0_secondary = maps\mp\alien\_persistence::get_selected_perk_0_secondary();
}
if ( !isDefined( perk_level_list ) )
{
return ( perk_name == selected_perk_0 || perk_name == selected_perk_1 || perk_name == selected_perk_0_secondary );
}
else
{
is_selected_perk_0_at_level = ( perk_name == selected_perk_0 && common_scripts\utility::array_contains( perk_level_list, perk_0_level ) );
is_selected_perk_1_at_level = ( perk_name == selected_perk_1 && common_scripts\utility::array_contains( perk_level_list, perk_1_level ) );
is_selected_perk_0_secondary_at_level = ( perk_name == selected_perk_0_secondary && common_scripts\utility::array_contains( perk_level_list, perk_0_level ) );
return ( is_selected_perk_0_at_level || is_selected_perk_1_at_level || is_selected_perk_0_secondary_at_level );
}
}
is_valid_perk( perk_name )
{
perk_0_list = GetArrayKeys( level.alien_perks["perk_0"] );
if ( common_scripts\utility::array_contains( perk_0_list, perk_name ) )
return true;
perk_1_list = GetArrayKeys( level.alien_perks["perk_1"] );
return common_scripts\utility::array_contains( perk_1_list, perk_name );
}

View File

@ -0,0 +1,963 @@
#include maps\mp\_utility;
#include maps\mp\alien\_utility;
#include maps\mp\alien\_perk_utility;
init_perk_none()
{
perk_data = spawnStruct();
return perk_data;
}
set_perk_none()
{
}
unset_perk_none()
{
}
////////////////////////////////////////
/// Tank Perks ///
////////////////////////////////////////
DEFAULT_MAX_HEALTH = 100;
LEVEL_0_MAX_HEALTH = 125;
LEVEL_1_MAX_HEALTH = 125;
LEVEL_2_MAX_HEALTH = 150;
LEVEL_3_MAX_HEALTH = 175;
LEVEL_4_MAX_HEALTH = 200;
DEFAULT_MELEE_SCALAR = 1.0;
LEVEL_1_MELEE_SCALAR = 1.25;
LEVEL_3_MELEE_SCALAR = 1.5;
LEVEL_4_MELEE_SCALAR = 2.0;
init_perk_health()
{
perk_data = spawnStruct();
perk_data.melee_scalar = DEFAULT_MELEE_SCALAR;
return perk_data;
}
set_perk_health_level_0()
{
self.perk_data[ "health" ].max_health = LEVEL_0_MAX_HEALTH;
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
unset_perk_health_level_0()
{
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
set_perk_health_level_1()
{
self.perk_data[ "health" ].max_health = LEVEL_1_MAX_HEALTH;
self.maxhealth = self.perk_data[ "health" ].max_health;
self notify( "health_perk_upgrade" );
self.perk_data[ "health" ].melee_scalar = LEVEL_1_MELEE_SCALAR;
}
unset_perk_health_level_1()
{
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
set_perk_health_level_2()
{
self.perk_data[ "health" ].max_health = LEVEL_2_MAX_HEALTH;
self.maxhealth = self.perk_data[ "health" ].max_health;
self notify( "health_perk_upgrade" );
self.perk_data[ "health" ].melee_scalar = LEVEL_1_MELEE_SCALAR;
}
unset_perk_health_level_2()
{
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
set_perk_health_level_3()
{
self.perk_data[ "health" ].max_health = LEVEL_3_MAX_HEALTH;
self.maxhealth = self.perk_data[ "health" ].max_health;
self notify( "health_perk_upgrade" );
self.perk_data[ "health" ].melee_scalar = LEVEL_3_MELEE_SCALAR;
}
unset_perk_health_level_3()
{
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
set_perk_health_level_4()
{
self.perk_data[ "health" ].max_health = LEVEL_4_MAX_HEALTH;
self.maxhealth = self.perk_data[ "health" ].max_health;
self notify( "health_perk_upgrade" );
self.perk_data[ "health" ].melee_scalar = LEVEL_4_MELEE_SCALAR;
}
unset_perk_health_level_4()
{
self.perk_data[ "health" ].melee_scalar = DEFAULT_MELEE_SCALAR;
}
////////////////////////////////////////
/// Weapon Specialist Perks ///
//////////////////////////////////////
DEFAULT_BULLET_DAMAGE_SCALAR = 1.0;
LEVEL_0_BULLET_DAMAGE_SCALAR = 1.2;
LEVEL_2_BULLET_DAMAGE_SCALAR = 1.3;
LEVEL_3_BULLET_DAMAGE_SCALAR = 1.4;
LEVEL_4_BULLET_DAMAGE_SCALAR = 1.5;
init_perk_bullet_damage()
{
perk_data = spawnStruct();
perk_data.bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
return perk_data;
}
set_perk_bullet_damage_0()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = LEVEL_0_BULLET_DAMAGE_SCALAR;
}
unset_perk_bullet_damage_0()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
}
set_perk_bullet_damage_1()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = LEVEL_0_BULLET_DAMAGE_SCALAR;
self givePerk( "specialty_quickswap", false );
self givePerk( "specialty_stalker", false );
self givePerk( "specialty_fastoffhand", false );
}
unset_perk_bullet_damage_1()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
self _unsetPerk( "specialty_quickswap" );
self _unsetPerk( "specialty_stalker" );
self _unsetPerk( "specialty_fastoffhand" );
}
set_perk_bullet_damage_2()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = LEVEL_0_BULLET_DAMAGE_SCALAR;
self givePerk( "specialty_quickswap", false );
self givePerk( "specialty_stalker", false );
self givePerk( "specialty_fastoffhand", false );
self givePerk( "specialty_quickdraw", false );
}
unset_perk_bullet_damage_2()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
self _unsetPerk( "specialty_quickswap" );
self _unsetPerk( "specialty_stalker" );
self _unsetPerk( "specialty_fastoffhand" );
self _unsetPerk( "specialty_quickdraw" );
}
set_perk_bullet_damage_3()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = LEVEL_0_BULLET_DAMAGE_SCALAR;
self givePerk( "specialty_quickswap", false );
self givePerk( "specialty_stalker", false );
self givePerk( "specialty_fastoffhand", false );
self givePerk( "specialty_quickdraw", false );
self givePerk( "specialty_fastreload", false );
}
unset_perk_bullet_damage_3()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
self _unsetPerk( "specialty_quickswap" );
self _unsetPerk( "specialty_stalker" );
self _unsetPerk( "specialty_fastoffhand" );
self _unsetPerk( "specialty_quickdraw" );
self givePerk( "specialty_fastreload", false );
}
set_perk_bullet_damage_4()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = LEVEL_4_BULLET_DAMAGE_SCALAR;
self givePerk( "specialty_quickswap", false );
self givePerk( "specialty_stalker", false );
self givePerk( "specialty_fastoffhand", false );
self givePerk( "specialty_quickdraw", false );
self setaimspreadmovementscale( 0.5 );
self givePerk( "specialty_fastreload", false );
}
unset_perk_bullet_damage_4()
{
self.perk_data[ "damagemod" ].bullet_damage_scalar = DEFAULT_BULLET_DAMAGE_SCALAR;
self _unsetPerk( "specialty_quickswap" );
self _unsetPerk( "specialty_stalker" );
self _unsetPerk( "specialty_fastoffhand" );
self _unsetPerk( "specialty_quickdraw" );
self setaimspreadmovementscale( 1.0 );
self _unsetPerk( "specialty_fastreload" );
}
////////////////////////////////////////
/// perk_medic ///
////////////////////////////////////////
DEFAULT_GAS_DAMAGE_SCALAR = 1.0;
LEVEL_1_MEDIC_GAS_DAMAGE_SCALAR = 0.0;
DEFAULT_REVIVE_TIME_SCALAR = 1.0;
LEVEL_0_MEDIC_REVIVE_TIME_SCALAR = 1.5;
LEVEL_2_MEDIC_REGEN_RATE = 5.0; // 5 points per second to nearby allies
LEVEL_2_MEDIC_HEALTH_REGEN_DIST_SQR = 65536.0; // 256.0 * 256.0
LEVEL_4_MEDIC_HEALTH_REGEN_DIST_SQR = 0.0; // Infinite distance
DEFAULT_MOVE_SPEED_SCALAR = 1.0;
LEVEL_2_MOVE_SPEED_SCALAR = 1.06;
LEVEL_4_MOVE_SPEED_SCALAR = 1.12;
DEFAULT_REVIVE_DAMAGE_SCALAR = 1.0;
LEVEL_3_REVIVE_DAMAGE_SCALAR = 0.75;
init_perk_medic()
{
perk_data = spawnStruct();
perk_data.revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
perk_data.gas_damage_scalar = DEFAULT_GAS_DAMAGE_SCALAR;
perk_data.move_speed_scalar = DEFAULT_MOVE_SPEED_SCALAR;
perk_data.revive_damage_scalar = DEFAULT_REVIVE_DAMAGE_SCALAR;
return perk_data;
}
set_perk_medic_0()
{
self.perk_data[ "medic" ].revive_time_scalar = LEVEL_0_MEDIC_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
}
unset_perk_medic_0()
{
self.perk_data[ "medic" ].revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = DEFAULT_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
}
set_perk_medic_1()
{
self.perk_data[ "medic" ].revive_time_scalar = LEVEL_0_MEDIC_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = LEVEL_2_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = LEVEL_3_REVIVE_DAMAGE_SCALAR;
}
unset_perk_medic_1()
{
self.perk_data[ "medic" ].revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = DEFAULT_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = DEFAULT_REVIVE_DAMAGE_SCALAR;
}
set_perk_medic_2()
{
self givePerk( "specialty_longersprint", false );
self thread medic_health_regen( LEVEL_2_MEDIC_HEALTH_REGEN_DIST_SQR );
self.perk_data[ "medic" ].revive_time_scalar = LEVEL_0_MEDIC_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = LEVEL_2_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = LEVEL_3_REVIVE_DAMAGE_SCALAR;
}
unset_perk_medic_2()
{
self _unsetPerk( "specialty_longersprint" );
self notify( "end_medic_health_regen" );
self.perk_data[ "medic" ].revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = DEFAULT_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = DEFAULT_REVIVE_DAMAGE_SCALAR;
}
set_perk_medic_3()
{
self.perk_data[ "medic" ].gas_damage_scalar = LEVEL_1_MEDIC_GAS_DAMAGE_SCALAR;
self givePerk( "specialty_longersprint", false );
self thread medic_health_regen( LEVEL_2_MEDIC_HEALTH_REGEN_DIST_SQR );
self.perk_data[ "medic" ].revive_time_scalar = LEVEL_0_MEDIC_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = LEVEL_2_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = LEVEL_3_REVIVE_DAMAGE_SCALAR;
}
unset_perk_medic_3()
{
self.perk_data[ "medic" ].gas_damage_scalar = DEFAULT_GAS_DAMAGE_SCALAR;
self _unsetPerk( "specialty_longersprint" );
self notify( "end_medic_health_regen" );
self.perk_data[ "medic" ].revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
self.moveSpeedScaler = DEFAULT_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self.perk_data[ "medic" ].revive_damage_scalar = DEFAULT_REVIVE_DAMAGE_SCALAR;
}
set_perk_medic_4()
{
self.perk_data[ "medic" ].revive_time_scalar = LEVEL_0_MEDIC_REVIVE_TIME_SCALAR;
self.perk_data[ "medic" ].gas_damage_scalar = LEVEL_1_MEDIC_GAS_DAMAGE_SCALAR;
self thread medic_health_regen( LEVEL_4_MEDIC_HEALTH_REGEN_DIST_SQR );
self.moveSpeedScaler = LEVEL_4_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self givePerk( "specialty_longersprint", false );
self givePerk( "specialty_fastsprintrecovery", false );
self.perk_data[ "medic" ].revive_damage_scalar = LEVEL_3_REVIVE_DAMAGE_SCALAR;
}
unset_perk_medic_4()
{
self.perk_data[ "medic" ].revive_time_scalar = DEFAULT_REVIVE_TIME_SCALAR;
self.perk_data[ "medic" ].gas_damage_scalar = DEFAULT_GAS_DAMAGE_SCALAR;
self notify( "end_medic_health_regen" );
self.moveSpeedScaler = DEFAULT_MOVE_SPEED_SCALAR * self maps\mp\alien\_prestige::prestige_getMoveSlowScalar();
self.perk_data[ "medic" ].move_speed_scalar = self.moveSpeedScaler;
self _unsetPerk( "specialty_longersprint" );
self _unsetPerk( "specialty_fastsprintrecovery" );
self.perk_data[ "medic" ].revive_damage_scalar = DEFAULT_REVIVE_DAMAGE_SCALAR;
}
medic_health_regen( dist_sqr )
{
self endon( "death" );
self endon( "disconnect" );
self endon( "end_medic_health_regen" );
do_dist_check = dist_sqr > 0.0;
while ( 1 )
{
foreach ( player in level.players ) // Includes self
{
if ( isReallyAlive( player )
&& !isDefined( player.medic_regeneration ) )
{
if ( do_dist_check && DistanceSquared( self.origin, player.origin ) > dist_sqr )
{
continue;
}
player thread medic_regenerate_health_once();
}
}
wait 1.0;
}
}
medic_regenerate_health_once()
{
self endon( "death" );
self endon( "disconnect" );
if ( !self has_fragile_relic_and_is_sprinting() )
{
self.medic_regeneration = true;
wait 1.0;
self.health = int( min( self.maxhealth, self.health + LEVEL_2_MEDIC_REGEN_RATE ) );
self.medic_regeneration = undefined;
}
}
////////////////////////////////////////
/// Engineer Perks ///
////////////////////////////////////////
DEFAULT_DRILL_HEALTH_SCALAR = 1.0;
LEVEL_0_DRILL_HEALTH_SCALAR = 1.256;
DEFAULT_DRILL_TIME_SCALAR = 1.0;
LEVEL_1_DRILL_TIME_SCALAR = 0.5;
DEFAULT_TRAP_COST_SCALAR = 1;
LEVEL_2_TRAP_COST_SCALAR = 0.8;
DEFAULT_TRAP_DURATION_SCALAR = 1;
LEVEL_3_TRAP_DURATION_SCALAR = 1.5;
DEFAULT_TRAP_DAMAGE_SCALAR = 1;
LEVEL_4_TRAP_DAMAGE_SCALAR = 2;
DEFAULT_MONEY_SCALE_PER_HIVE = 1.0;
LEVEL_0_MONEY_SCALE_PER_HIVE = 1.2;
DEFAULT_WALLET_SIZE = 6000;
LEVEL_4_WALLET_SIZE = 8000;
DEFAULT_EXPLOSIVE_DAMAGE_SCALAR = 1.0;
LEVEL_4_EXPLOSIVE_DAMAGE_SCALAR = 1.5;
DEFAULT_REPAIR_DAMAGE_SCALAR = 1.0;
LEVEL_3_REPAIR_DAMAGE_SCALAR = 0.75;
init_perk_rigger()
{
perk_data = spawnStruct();
perk_data.drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
perk_data.drill_time_scalar = DEFAULT_DRILL_TIME_SCALAR;
perk_data.trap_cost_scalar = DEFAULT_TRAP_COST_SCALAR;
perk_data.trap_duration_scalar = DEFAULT_TRAP_DURATION_SCALAR;
perk_data.trap_damage_scalar = DEFAULT_TRAP_DAMAGE_SCALAR;
perk_data.currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
perk_data.explosive_damage_scalar = DEFAULT_EXPLOSIVE_DAMAGE_SCALAR;
perk_data.repair_damage_scalar = DEFAULT_REPAIR_DAMAGE_SCALAR;
return perk_data;
}
set_perk_rigger_0()
{
self.perk_data[ "rigger" ].drill_health_scalar = LEVEL_0_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = LEVEL_0_MONEY_SCALE_PER_HIVE;
}
unset_perk_rigger_0()
{
self.perk_data[ "rigger" ].drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
}
set_perk_rigger_1()
{
self.perk_data[ "rigger" ].drill_health_scalar = LEVEL_0_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = LEVEL_0_MONEY_SCALE_PER_HIVE;
self.perk_data[ "rigger" ].drill_time_scalar = LEVEL_1_DRILL_TIME_SCALAR;
}
unset_perk_rigger_1()
{
self.perk_data[ "rigger" ].drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].drill_time_scalar = DEFAULT_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
}
set_perk_rigger_2()
{
self.perk_data[ "rigger" ].drill_health_scalar = LEVEL_0_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = LEVEL_0_MONEY_SCALE_PER_HIVE;
self.perk_data[ "rigger" ].drill_time_scalar = LEVEL_1_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = LEVEL_2_TRAP_COST_SCALAR;
}
unset_perk_rigger_2()
{
self.perk_data[ "rigger" ].drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].drill_time_scalar = DEFAULT_TRAP_COST_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = DEFAULT_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
}
set_perk_rigger_3()
{
self.perk_data[ "rigger" ].drill_health_scalar = LEVEL_0_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = LEVEL_0_MONEY_SCALE_PER_HIVE;
self.perk_data[ "rigger" ].drill_time_scalar = LEVEL_1_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = LEVEL_2_TRAP_COST_SCALAR;
self.perk_data[ "rigger" ].trap_duration_scalar = LEVEL_3_TRAP_DURATION_SCALAR;
self.perk_data[ "rigger" ].repair_damage_scalar = LEVEL_3_REPAIR_DAMAGE_SCALAR;
}
unset_perk_rigger_3()
{
self.perk_data[ "rigger" ].drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].drill_time_scalar = DEFAULT_TRAP_COST_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = DEFAULT_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].trap_duration_scalar = DEFAULT_TRAP_DURATION_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
self.perk_data[ "rigger" ].repair_damage_scalar = DEFAULT_REPAIR_DAMAGE_SCALAR;
}
set_perk_rigger_4()
{
self.perk_data[ "rigger" ].drill_health_scalar = LEVEL_0_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = LEVEL_0_MONEY_SCALE_PER_HIVE;
self.perk_data[ "rigger" ].drill_time_scalar = LEVEL_1_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = LEVEL_2_TRAP_COST_SCALAR;
self.perk_data[ "rigger" ].trap_duration_scalar = LEVEL_3_TRAP_DURATION_SCALAR;
self.perk_data[ "rigger" ].trap_damage_scalar = LEVEL_4_TRAP_DAMAGE_SCALAR;
self maps\mp\alien\_persistence::set_player_max_currency( LEVEL_4_WALLET_SIZE * maps\mp\alien\_prestige::prestige_getWalletSizeScalar() );
self.perk_data[ "rigger" ].repair_damage_scalar = LEVEL_3_REPAIR_DAMAGE_SCALAR;
self.perk_data[ "rigger" ].explosive_damage_scalar = LEVEL_4_EXPLOSIVE_DAMAGE_SCALAR;
}
unset_perk_rigger_4()
{
self.perk_data[ "rigger" ].drill_health_scalar = DEFAULT_DRILL_HEALTH_SCALAR;
self.perk_data[ "rigger" ].drill_time_scalar = DEFAULT_TRAP_COST_SCALAR;
self.perk_data[ "rigger" ].trap_cost_scalar = DEFAULT_DRILL_TIME_SCALAR;
self.perk_data[ "rigger" ].trap_duration_scalar = DEFAULT_TRAP_DURATION_SCALAR;
self.perk_data[ "rigger" ].trap_damage_scalar = DEFAULT_TRAP_DAMAGE_SCALAR;
self.perk_data[ "rigger" ].currency_scale_per_hive = DEFAULT_MONEY_SCALE_PER_HIVE;
self maps\mp\alien\_persistence::set_player_max_currency( DEFAULT_WALLET_SIZE * maps\mp\alien\_prestige::prestige_getWalletSizeScalar() );
self.perk_data[ "rigger" ].repair_damage_scalar = DEFAULT_REPAIR_DAMAGE_SCALAR;
self.perk_data[ "rigger" ].explosive_damage_scalar = DEFAULT_EXPLOSIVE_DAMAGE_SCALAR;
}
////////////////////////////////////////
/// Pistol Perk Data Init ///
////////////////////////////////////////
init_perk_pistol()
{
perk_data = spawnStruct();
perk_data.pistol_overkill = false;
perk_data.pistol_regen = false;
return perk_data;
}
check_for_pistol_ammo( base_pistol_name, full_pistol_name )
{
self.lastWeapon = self GetCurrentWeapon();
self.pistol_clip_ammo_right = self GetWeaponAmmoClip( full_pistol_name, "right" );
self.pistol_ammo_remaining = self GetWeaponAmmoStock( full_pistol_name );
}
give_new_pistol( new_pistol_name )
{
pistol = new_pistol_name;
self _giveWeapon( pistol );
self SetWeaponAmmoClip( pistol, self.pistol_clip_ammo_right, "right" );
self SetWeaponAmmoStock( pistol, self.pistol_ammo_remaining );
weaponlist = self GetWeaponsListPrimaries();
if ( !self HasWeapon( self.lastWeapon ) && !self has_special_weapon() && !self is_holding_deployable() )
self SwitchToWeapon( pistol );
}
////////////////////////////////////////
/// Pistol P226 Perk ///
////////////////////////////////////////
set_perk_pistol_p226_0()
{
}
unset_perk_pistol_p226_0()
{
self store_ammo_and_take_pistol( "iw6_alienp226_mp" );
}
set_perk_pistol_p226_1()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienp226_mp_alienmuzzlebrakepi" );
else
self give_new_pistol( "iw6_alienp226_mp_barrelrange02" );
//We are setting combatspeedscalar for all pistol Rank 1.
}
unset_perk_pistol_p226_1()
{
self store_ammo_and_take_pistol( "iw6_alienp226_mp" );
}
set_perk_pistol_p226_2()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienp226_mp_alienmuzzlebrakepi_xmags" );
else
self give_new_pistol( "iw6_alienp226_mp_barrelrange02_xmags" );
}
unset_perk_pistol_p226_2()
{
self store_ammo_and_take_pistol( "iw6_alienp226_mp" );
}
set_perk_pistol_p226_3()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienp226_mp_alienmuzzlebrakepi_xmags" );
else
self give_new_pistol( "iw6_alienp226_mp_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_p226_3()
{
self store_ammo_and_take_pistol( "iw6_alienp226_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
set_perk_pistol_p226_4()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienp226_mp_akimbo_alienmuzzlebrakepi_xmags" );
else
self give_new_pistol( "iw5_alienp226_mp_akimbo_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_p226_4()
{
self store_ammo_and_take_pistol( "iw5_alienp226_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
////////////////////////////////////////
/// Pistol Magnum Perk ///
////////////////////////////////////////
set_perk_pistol_magnum_0()
{
}
unset_perk_pistol_magnum_0()
{
self store_ammo_and_take_pistol( "iw6_alienmagnum_mp" );
}
set_perk_pistol_magnum_1()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && !self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_barrelrange02_scope5" );
else if ( !self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_alienmuzzlebrakepi" );
else if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_alienmuzzlebrakepi_scope5" );
else
self give_new_pistol( "iw6_alienmagnum_mp_barrelrange02" );
}
unset_perk_pistol_magnum_1()
{
self store_ammo_and_take_pistol( "iw6_alienmagnum_mp" );
}
set_perk_pistol_magnum_2()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && !self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_barrelrange02_xmags_scope5" );
else if ( !self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_alienmuzzlebrakepi_xmags" );
else if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_alienmuzzlebrakepi_xmags_scope5" );
else
self give_new_pistol( "iw6_alienmagnum_mp_barrelrange02_xmags" );
}
unset_perk_pistol_magnum_2()
{
self store_ammo_and_take_pistol( "iw6_alienmagnum_mp" );
}
set_perk_pistol_magnum_3()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && !self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_barrelrange02_xmags_scope5" );
else if ( !self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_alienmuzzlebrakepi_xmags" );
else if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmagnum_mp_acogpistol_alienmuzzlebrakepi_xmags_scope5" );
else
self give_new_pistol( "iw6_alienmagnum_mp_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_magnum_3()
{
self store_ammo_and_take_pistol( "iw6_alienmagnum_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
set_perk_pistol_magnum_4()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && !self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienmagnum_mp_acogpistol_akimbo_barrelrange02_xmags_scope5" );
else if ( !self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienmagnum_mp_akimbo_alienmuzzlebrakepi_xmags" );
else if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "magnum_acog_upgrade" ) && self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienmagnum_mp_acogpistol_akimbo_alienmuzzlebrakepi_xmags_scope5" );
else
self give_new_pistol( "iw5_alienmagnum_mp_akimbo_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_magnum_4()
{
self store_ammo_and_take_pistol( "iw5_alienmagnum_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
////////////////////////////////////////
/// Pistol M9A1 Perk ///
////////////////////////////////////////
set_perk_pistol_m9a1_0()
{
}
unset_perk_pistol_m9a1_0()
{
self store_ammo_and_take_pistol( "iw6_alienm9a1_mp" );
}
set_perk_pistol_m9a1_1()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienm9a1_mp_alienmuzzlebrakep3" );
else
self give_new_pistol( "iw6_alienm9a1_mp_barrelrange02" );
}
unset_perk_pistol_m9a1_1()
{
self store_ammo_and_take_pistol( "iw6_alienm9a1_mp" );
}
set_perk_pistol_m9a1_2()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienm9a1_mp_alienmuzzlebrakep3_xmags" );
else
self give_new_pistol( "iw6_alienm9a1_mp_barrelrange02_xmags" );
}
unset_perk_pistol_m9a1_2()
{
self store_ammo_and_take_pistol( "iw6_alienm9a1_mp" );
}
set_perk_pistol_m9a1_3()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienm9a1_mp_alienmuzzlebrakep3_xmags" );
else
self give_new_pistol( "iw6_alienm9a1_mp_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_m9a1_3()
{
self store_ammo_and_take_pistol( "iw6_alienm9a1_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
set_perk_pistol_m9a1_4()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienm9a1_mp_akimbo_alienmuzzlebrakep3_xmags" );
else
self give_new_pistol( "iw5_alienm9a1_mp_akimbo_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_m9a1_4()
{
self store_ammo_and_take_pistol( "iw5_alienm9a1_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
/*
get_current_pistol()
{
weap_list = self GetWeaponsListPrimaries();
foreach ( weap in weap_list )
{
weap_class = getWeaponClass ( weap );
if ( weap_class == "weapon_pistol" )
{
return weap;
}
}
}
*/
store_ammo_and_take_pistol( baseweapon )
{
current_pistol = self get_current_pistol();
self check_for_pistol_ammo ( baseweapon, current_pistol );
self TakeWeapon( current_pistol );
}
////////////////////////////////////////
/// Pistol MP443 Perk ///
////////////////////////////////////////
set_perk_pistol_mp443_0()
{
}
unset_perk_pistol_mp443_0()
{
self store_ammo_and_take_pistol( "iw6_alienmp443_mp" );
}
set_perk_pistol_mp443_1()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmp443_mp_alienmuzzlebrakepa" );
else
self give_new_pistol( "iw6_alienmp443_mp_barrelrange02" );
}
unset_perk_pistol_mp443_1()
{
self store_ammo_and_take_pistol( "iw6_alienmp443_mp" );
}
set_perk_pistol_mp443_2()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmp443_mp_alienmuzzlebrakepa_xmags" );
else
self give_new_pistol( "iw6_alienmp443_mp_barrelrange02_xmags" );
}
unset_perk_pistol_mp443_2()
{
self store_ammo_and_take_pistol( "iw6_alienmp443_mp" );
}
set_perk_pistol_mp443_3()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw6_alienmp443_mp_alienmuzzlebrakepa_xmags" );
else
self give_new_pistol( "iw6_alienmp443_mp_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_mp443_3()
{
self store_ammo_and_take_pistol( "iw6_alienmp443_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
set_perk_pistol_mp443_4()
{
if ( self maps\mp\alien\_persistence::is_upgrade_enabled( "ark_pistol_upgrade" ) )
self give_new_pistol( "iw5_alienmp443_mp_akimbo_alienmuzzlebrakepa_xmags" );
else
self give_new_pistol( "iw5_alienmp443_mp_akimbo_barrelrange02_xmags" );
self.perk_data[ "pistol" ].pistol_overkill = true;
}
unset_perk_pistol_mp443_4()
{
self store_ammo_and_take_pistol( "iw5_alienmp443_mp" );
self.perk_data[ "pistol" ].pistol_overkill = false;
}
///////////////////////////////////////////////////////
// //
// Pistol Speed Perk //
// //
/////////////////////////////////////////////////////
watchCombatSpeedScaler()
{
self endon( "death" );
self endon( "disconnect" );
self.pistolCombatSpeedScalar = 1.0;
self.alienSnareSpeedScalar = 1.0;
self.alienSnareCount = 0;
self.combatSpeedScalar = getCombatSpeedScalar();
self maps\mp\gametypes\_weapons::updateMoveSpeedScale();
while ( true )
{
self waittill ( "weapon_change", newWeapon );
if ( self has_perk( "perk_pistol_p226", [1,2,3,4] ) || self has_perk( "perk_pistol_magnum", [1,2,3,4] ) || self has_perk( "perk_pistol_m9a1", [1,2,3,4] ) || self has_perk( "perk_pistol_mp443", [1,2,3,4] ) )
{
currentweapon = self GetCurrentWeapon();
baseweapon = getRawBaseWeaponName( currentweapon );
if ( IsDefined( baseweapon ) )
{
if ( baseweapon == "alienp226" || baseweapon == "alienmagnum" || baseweapon == "alienm9a1" || baseweapon == "alienmp443" )
{
self.pistolCombatSpeedScalar = 1.1;
}
else
{
self.pistolCombatSpeedScalar = 1.0;
}
wait 0.05; //Don't want to risk called this twice in the same frame since it's already called onm weapon_change
updateCombatSpeedScalar();
}
}
wait 0.05;
}
}
updateCombatSpeedScalar()
{
self.combatSpeedScalar = getCombatSpeedScalar();
self maps\mp\gametypes\_weapons::updateMoveSpeedScale();
}
getCombatSpeedScalar()
{
return ( self.pistolCombatSpeedScalar * self.alienSnareSpeedScalar );
}
watchFlamingRiotShield()
{
self endon( "death" );
self endon( "disconnect" );
while ( true )
{
currentweapon = self GetCurrentWeapon();
if ( IsDefined( currentweapon ) )
{
if ( currentweapon == "iw5_alienriotshield4_mp_camo05" && self.fireShield == 1.0 )
{
PlayFXOnTag( level._effect[ "Riotshield_fire" ], self, "TAG_origin" );
}
else
{
StopFXOnTag( level._effect[ "Riotshield_fire" ], self, "TAG_origin" );
}
}
}
wait 0.05;
}

223
maps/mp/alien/_perks.gsc Normal file
View File

@ -0,0 +1,223 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\agents\_agent_utility;
#include maps\mp\alien\_utility;
#include maps\mp\alien\_perkfunctions;
init_perks()
{
init_perks_callback();
init_perks_from_table();
}
PERK_TABLE = "mp/alien/perks_tree.csv";
init_perks_from_table()
{
// level.alien_perks_table can be used to override default table, should be set before _alien::main()
if ( !isdefined( level.alien_perks_table ) )
level.alien_perks_table = PERK_TABLE;
level.alien_perks = [];
update_perks_from_table( 0, "perk_0" );
update_perks_from_table( 100, "perk_1" );
}
init_perks_callback()
{
level.alien_perk_callbacks = [];
register_perk_callback( "perk_health", ::set_perk_health_level_0, ::unset_perk_health_level_0 );
register_perk_callback( "perk_health_1", ::set_perk_health_level_1, ::unset_perk_health_level_1 );
register_perk_callback( "perk_health_2", ::set_perk_health_level_2, ::unset_perk_health_level_2 );
register_perk_callback( "perk_health_3", ::set_perk_health_level_3, ::unset_perk_health_level_3 );
register_perk_callback( "perk_health_4", ::set_perk_health_level_4, ::unset_perk_health_level_4 );
register_perk_callback( "perk_pistol_p226", ::set_perk_pistol_p226_0, ::unset_perk_pistol_p226_0 );
register_perk_callback( "perk_pistol_p226_1", ::set_perk_pistol_p226_1, ::unset_perk_pistol_p226_1 );
register_perk_callback( "perk_pistol_p226_2", ::set_perk_pistol_p226_2, ::unset_perk_pistol_p226_2 );
register_perk_callback( "perk_pistol_p226_3", ::set_perk_pistol_p226_3, ::unset_perk_pistol_p226_3 );
register_perk_callback( "perk_pistol_p226_4", ::set_perk_pistol_p226_4, ::unset_perk_pistol_p226_4 );
register_perk_callback( "perk_pistol_magnum", ::set_perk_pistol_magnum_0, ::unset_perk_pistol_magnum_0 );
register_perk_callback( "perk_pistol_magnum_1", ::set_perk_pistol_magnum_1, ::unset_perk_pistol_magnum_1 );
register_perk_callback( "perk_pistol_magnum_2", ::set_perk_pistol_magnum_2, ::unset_perk_pistol_magnum_2 );
register_perk_callback( "perk_pistol_magnum_3", ::set_perk_pistol_magnum_3, ::unset_perk_pistol_magnum_3 );
register_perk_callback( "perk_pistol_magnum_4", ::set_perk_pistol_magnum_4, ::unset_perk_pistol_magnum_4 );
register_perk_callback( "perk_pistol_m9a1", ::set_perk_pistol_m9a1_0, ::unset_perk_pistol_m9a1_0 );
register_perk_callback( "perk_pistol_m9a1_1", ::set_perk_pistol_m9a1_1, ::unset_perk_pistol_m9a1_1 );
register_perk_callback( "perk_pistol_m9a1_2", ::set_perk_pistol_m9a1_2, ::unset_perk_pistol_m9a1_2 );
register_perk_callback( "perk_pistol_m9a1_3", ::set_perk_pistol_m9a1_3, ::unset_perk_pistol_m9a1_3 );
register_perk_callback( "perk_pistol_m9a1_4", ::set_perk_pistol_m9a1_4, ::unset_perk_pistol_m9a1_4 );
register_perk_callback( "perk_pistol_mp443", ::set_perk_pistol_mp443_0, ::unset_perk_pistol_mp443_0 );
register_perk_callback( "perk_pistol_mp443_1", ::set_perk_pistol_mp443_1, ::unset_perk_pistol_mp443_1 );
register_perk_callback( "perk_pistol_mp443_2", ::set_perk_pistol_mp443_2, ::unset_perk_pistol_mp443_2 );
register_perk_callback( "perk_pistol_mp443_3", ::set_perk_pistol_mp443_3, ::unset_perk_pistol_mp443_3 );
register_perk_callback( "perk_pistol_mp443_4", ::set_perk_pistol_mp443_4, ::unset_perk_pistol_mp443_4 );
register_perk_callback( "perk_bullet_damage", ::set_perk_bullet_damage_0, ::unset_perk_bullet_damage_0 );
register_perk_callback( "perk_bullet_damage_1", ::set_perk_bullet_damage_1, ::unset_perk_bullet_damage_1 );
register_perk_callback( "perk_bullet_damage_2", ::set_perk_bullet_damage_2, ::unset_perk_bullet_damage_2 );
register_perk_callback( "perk_bullet_damage_3", ::set_perk_bullet_damage_3, ::unset_perk_bullet_damage_3 );
register_perk_callback( "perk_bullet_damage_4", ::set_perk_bullet_damage_4, ::unset_perk_bullet_damage_4 );
register_perk_callback( "perk_medic", ::set_perk_medic_0, ::unset_perk_medic_0 );
register_perk_callback( "perk_medic_1", ::set_perk_medic_1, ::unset_perk_medic_1 );
register_perk_callback( "perk_medic_2", ::set_perk_medic_2, ::unset_perk_medic_2 );
register_perk_callback( "perk_medic_3", ::set_perk_medic_3, ::unset_perk_medic_3 );
register_perk_callback( "perk_medic_4", ::set_perk_medic_4, ::unset_perk_medic_4 );
register_perk_callback( "perk_rigger", ::set_perk_rigger_0, ::unset_perk_rigger_0 );
register_perk_callback( "perk_rigger_1", ::set_perk_rigger_1, ::unset_perk_rigger_1 );
register_perk_callback( "perk_rigger_2", ::set_perk_rigger_2, ::unset_perk_rigger_2 );
register_perk_callback( "perk_rigger_3", ::set_perk_rigger_3, ::unset_perk_rigger_3 );
register_perk_callback( "perk_rigger_4", ::set_perk_rigger_4, ::unset_perk_rigger_4 );
register_perk_callback( "perk_none", ::set_perk_none, ::unset_perk_none );
register_perk_callback( "perk_none_1", ::set_perk_none, ::unset_perk_none );
register_perk_callback( "perk_none_2", ::set_perk_none, ::unset_perk_none );
register_perk_callback( "perk_none_3", ::set_perk_none, ::unset_perk_none );
register_perk_callback( "perk_none_4", ::set_perk_none, ::unset_perk_none );
}
register_perk_callback( perk_name, set_func, unSet_func )
{
perk_callback = spawnstruct();
perk_callback.Set = set_func;
perk_callback.unSet = unSet_func;
level.alien_perk_callbacks[ perk_name ] = perk_callback;
}
// ================================================================
// Perks Table
// ================================================================
TABLE_INDEX = 0; // [int] Indexing
TABLE_REF = 1; // [string] Reference
TABLE_UNLOCK = 2; // [int] Unlocked at rank number
TABLE_POINT_COST = 3; // [int] Combat point cost to enable this perk(upgrades)
TABLE_NAME = 4; // [string] Name localized
TABLE_DESC = 5; // [string] Description localized
TABLE_ICON = 6; // [string] Reference string of icon for perk
TABLE_IS_UPGRADE = 7; // [int] 1 if this is an upgrade, 0 if not
TABLE_PERK_MAX_INDEX = 100;
// Populates data table entries into level array
update_perks_from_table( start_idx, perk_type )
{
level.alien_perks[ perk_type ] = [];
for ( i = start_idx; i <= start_idx + TABLE_PERK_MAX_INDEX; i++ )
{
// break on end of line
perk_ref = get_perk_ref_by_index( i );
if ( perk_ref == "" ) { break; }
if ( !isdefined( level.alien_perks[ perk_ref ] ) )
{
perk = spawnstruct();
perk.upgrades = [];
perk.unlock = get_unlock_by_ref( perk_ref );
perk.name = get_name_by_ref( perk_ref );
perk.icon = get_icon_by_ref( perk_ref );
perk.ref = perk_ref;
perk.type = perk_type;
perk.callbacks = level.alien_perk_callbacks[ perk_ref ];
perk.baseIdx = i;
level.alien_perks[ perk_type ][ perk_ref ] = perk;
}
// grab all upgrades for this perk
for ( j = i; j <= start_idx + TABLE_PERK_MAX_INDEX; j++ )
{
upgrade_ref = get_perk_ref_by_index( j );
if ( upgrade_ref == "" ) { break; }
if ( upgrade_ref == perk_ref || is_perk_set( perk_ref, upgrade_ref ) )
{
upgrade = spawnstruct();
upgrade.ref = upgrade_ref;
upgrade.desc = get_desc_by_ref( upgrade_ref );
upgrade.point_cost = get_point_cost_by_ref( upgrade_ref );
level.alien_perks[ perk_type ][ perk_ref ].upgrades[ j - i ] = upgrade;
}
else
{
break;
}
}
// point index to next perk set
i = j - 1;
}
}
// returns true if upgrade_ref is/or an upgrade of perk_ref
is_perk_set( perk_ref, upgrade_ref )
{
// ex: "perk_blah" is perk ref
// all upgrade refs should be in form of "perk_blah_#"
assert( isdefined( perk_ref ) && isdefined( upgrade_ref ) );
if ( perk_ref == upgrade_ref )
return false;
if ( !issubstr( upgrade_ref, perk_ref ) )
return false;
perk_toks = StrTok( perk_ref, "_" );
upgrade_toks = StrTok( upgrade_ref, "_" );
if ( upgrade_toks.size - perk_toks.size != 1 )
return false;
for ( i = 0; i < upgrade_toks.size - 1; i++ )
{
if ( upgrade_toks[ i ] != perk_toks[ i ] )
return false;
}
return true;
}
get_perk_ref_by_index( index )
{
return tablelookup( level.alien_perks_table, TABLE_INDEX, index, TABLE_REF );
}
get_name_by_ref( ref )
{
return tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_NAME );
}
get_icon_by_ref( ref )
{
return tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_ICON );
}
get_desc_by_ref( ref )
{
return tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_DESC );
}
get_point_cost_by_ref( ref )
{
return int( tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_POINT_COST ) );
}
get_unlock_by_ref( ref )
{
return int( tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_UNLOCK ) );
}
get_is_upgrade_by_ref( ref )
{
return int( tablelookup( level.alien_perks_table, TABLE_REF, ref, TABLE_IS_UPGRADE ) );
}

File diff suppressed because it is too large Load Diff

2670
maps/mp/alien/_pillage.gsc Normal file

File diff suppressed because it is too large Load Diff

175
maps/mp/alien/_prestige.gsc Normal file
View File

@ -0,0 +1,175 @@
CONST_MAX_NUM_PRESTIGE_NERF = 32; // The max number of nerf options
CONST_NERF_TABLE = "mp/alien/prestige_nerf.csv";
CONST_NERF_TABLE_IDX_COLUMN = 0;
CONST_NERF_TABLE_REF_COLUMN = 1;
CONST_NERF_SCALAR_DAMAGE_TAKEN = 1.33; // Greater than 1 to make player takes more damage from aliens
CONST_NERF_SCALAR_THREATBIAS = 500; // Greater than 0 to make aliens attack this particular player more often
CONST_NERF_SCALAR_WALLET_SIZE = 0.5; // Less than 1 to make the wallet size smaller;
CONST_NERF_SCALAR_EARN_LESS_MONEY = 0.75; // Less then 1 to make player earn less money
CONST_NERF_SCALAR_WEAPON_DAMAGE = 0.66; // Less than 1 to make player do less damage on aliens;
CONST_NERF_NO_CLASS_ALLOWED = 1.0; // 1 = can't select a class, 0 or undefined means you can
CONST_NERF_PISTOLS_ONLY = 1.0; // 1 = can't but weapons, 0 or undefined means you can
CONST_NERF_SCALAR_HEALTH_REGEN = 1.5; // slow health regen by 50%
CONST_NERF_SCALAR_MOVE_SLOWER = 0.7; // movement scalar
CONST_NERF_NO_ABILITIES = 1.0; // 1 = can't use Left and Right Dpad abilities, 0 = you can use them
CONST_NERF_SCALAR_MIN_AMMO = 0.25; // scalar of max stock for give ammo calls
CONST_NERF_NO_DEPLOYABLES = 1.0; // 1 = can't use Up and Down Dpad abilities, 0 = you can use them
// Those name references need to match the "reference string" column in the prestige_nerf csv table
CONST_REF_NO_NERF = "none";
CONST_REF_TAKE_MORE_DAMAGE = "nerf_take_more_damage";
CONST_REF_HIGHER_THREATBIAS = "nerf_higher_threatbias";
CONST_REF_SMALLER_WALLET = "nerf_smaller_wallet";
CONST_REF_EARN_LESS_MONEY = "nerf_earn_less_money"; // This one is not in the prestige_nerf csv table. It is the additional nerf for smaller wallet
CONST_REF_LOWER_WEAPON_DAMAGE = "nerf_lower_weapon_damage";
CONST_REF_NO_CLASS_ALLOWED = "nerf_no_class";
CONST_REF_PISTOLS_ONLY = "nerf_pistols_only";
CONST_REF_SLOW_HEALTH_REGEN = "nerf_fragile";
CONST_REF_MOVE_SLOWER = "nerf_move_slower";
CONST_REF_NO_ABILITIES = "nerf_no_abilities";
CONST_REF_MIN_AMMO = "nerf_min_ammo";
CONST_REF_NO_DEPLOYABLES = "nerf_no_deployables";
init_prestige()
{
nerf_func = [];
nerf_func[CONST_REF_NO_NERF] = ::empty;
nerf_func[CONST_REF_TAKE_MORE_DAMAGE] = ::increase_damage_scalar;
nerf_func[CONST_REF_HIGHER_THREATBIAS] = ::increase_threatbias;
nerf_func[CONST_REF_SMALLER_WALLET] = ::reduce_wallet_size_and_money_earned;
nerf_func[CONST_REF_LOWER_WEAPON_DAMAGE] = ::lower_weapon_damage;
nerf_func[CONST_REF_NO_CLASS_ALLOWED] = ::no_class;
nerf_func[CONST_REF_PISTOLS_ONLY] = ::pistols_only;
nerf_func[CONST_REF_SLOW_HEALTH_REGEN] = ::slow_health_regen;
nerf_func[CONST_REF_MOVE_SLOWER] = ::move_slower;
nerf_func[CONST_REF_NO_ABILITIES] = ::no_abilities;
nerf_func[CONST_REF_MIN_AMMO] = ::min_ammo;
nerf_func[CONST_REF_NO_DEPLOYABLES] = ::no_deployables;
level.prestige_nerf_func = nerf_func;
table_list = [];
for( i = 0; i < CONST_MAX_NUM_PRESTIGE_NERF; i++ )
{
nerfRef = TableLookupByRow( CONST_NERF_TABLE, i, CONST_NERF_TABLE_REF_COLUMN );
if( !IsDefined( nerfRef ) || nerfRef == "" )
break;
table_list[table_list.size] = nerfRef;
}
level.nerf_list = table_list;
}
init_player_prestige()
{
init_nerf_scalar();
if ( is_relics_enabled() )
nerf_based_on_selection();
}
init_nerf_scalar()
{
nerf_scalars = [];
nerf_scalars[CONST_REF_TAKE_MORE_DAMAGE] = 1.0;
nerf_scalars[CONST_REF_HIGHER_THREATBIAS] = 0; //<NOTE J.C> Default threatbias value is 0
nerf_scalars[CONST_REF_SMALLER_WALLET] = 1.0;
nerf_scalars[CONST_REF_EARN_LESS_MONEY] = 1.0;
nerf_scalars[CONST_REF_LOWER_WEAPON_DAMAGE] = 1.0;
nerf_scalars[CONST_REF_NO_CLASS_ALLOWED] = 0; // 0 = can use classes
nerf_scalars[CONST_REF_PISTOLS_ONLY] = 0; // 0 = not pistols only, can buy weapons
nerf_scalars[CONST_REF_SLOW_HEALTH_REGEN] = 1.0; // default health regen scalar is 1
nerf_scalars[CONST_REF_MOVE_SLOWER] = 1.0; //Move speed scalar
nerf_scalars[CONST_REF_NO_ABILITIES] = 0; // 0 = can use abilities
nerf_scalars[CONST_REF_MIN_AMMO] = 1.0;
nerf_scalars[CONST_REF_NO_DEPLOYABLES] = 0; // 0 = can use abilities
self.nerf_scalars = nerf_scalars;
self.activated_nerfs = [];
}
nerf_based_on_selection()
{
foreach( nerf in level.nerf_list )
{
if ( self alienscheckisrelicenabled( nerf ) )
{
activate_nerf( nerf );
}
}
}
activate_nerf( reference )
{
register_nerf_activated( reference );
[[level.prestige_nerf_func[reference]]]();
}
nerf_already_activated( reference )
{
return common_scripts\utility::array_contains( self.activated_nerfs, reference );
}
register_nerf_activated( reference )
{
self.activated_nerfs[self.activated_nerfs.size] = reference;
}
reduce_wallet_size_and_money_earned()
{
reduce_wallet_size();
reduce_money_earned();
}
is_relics_enabled()
{
if ( maps\mp\alien\_utility::is_chaos_mode() )
return false;
return true;
}
is_no_nerf( reference ) { return reference == "none"; }
get_num_nerf_selected() { return self.activated_nerfs.size; }
empty() {}
increase_damage_scalar() { set_nerf_scalar( CONST_REF_TAKE_MORE_DAMAGE , CONST_NERF_SCALAR_DAMAGE_TAKEN ); }
increase_threatbias() { set_nerf_scalar( CONST_REF_HIGHER_THREATBIAS , CONST_NERF_SCALAR_THREATBIAS ); }
reduce_wallet_size() { set_nerf_scalar( CONST_REF_SMALLER_WALLET , CONST_NERF_SCALAR_WALLET_SIZE ); }
reduce_money_earned() { set_nerf_scalar( CONST_REF_EARN_LESS_MONEY , CONST_NERF_SCALAR_EARN_LESS_MONEY ); }
lower_weapon_damage() { set_nerf_scalar( CONST_REF_LOWER_WEAPON_DAMAGE , CONST_NERF_SCALAR_WEAPON_DAMAGE ); }
no_class() { set_nerf_scalar( CONST_REF_NO_CLASS_ALLOWED , CONST_NERF_NO_CLASS_ALLOWED ); }
pistols_only() { set_nerf_scalar( CONST_REF_PISTOLS_ONLY , CONST_NERF_PISTOLS_ONLY ); }
slow_health_regen() { set_nerf_scalar( CONST_REF_SLOW_HEALTH_REGEN , CONST_NERF_SCALAR_HEALTH_REGEN ); }
move_slower() { set_nerf_scalar( CONST_REF_MOVE_SLOWER , CONST_NERF_SCALAR_MOVE_SLOWER ); }
no_abilities() { set_nerf_scalar( CONST_REF_NO_ABILITIES , CONST_NERF_NO_ABILITIES ); }
min_ammo() { set_nerf_scalar( CONST_REF_MIN_AMMO , CONST_NERF_SCALAR_MIN_AMMO ); }
no_deployables() { set_nerf_scalar( CONST_REF_NO_DEPLOYABLES , CONST_NERF_NO_DEPLOYABLES ); }
set_nerf_scalar( field, value ) { self.nerf_scalars[field] = value; }
get_nerf_scalar( field ) { return self.nerf_scalars[field]; }
get_selected_nerf( index ) { return self getcoopplayerdata( "alienPlayerLoadout", "nerfs", index ); }
// Interface function for external systems
prestige_getDamageTakenScalar() { return get_nerf_scalar( CONST_REF_TAKE_MORE_DAMAGE ); }
prestige_getThreatbiasScalar() { return get_nerf_scalar( CONST_REF_HIGHER_THREATBIAS ); }
prestige_getWalletSizeScalar() { return get_nerf_scalar( CONST_REF_SMALLER_WALLET ); }
prestige_getMoneyEarnedScalar() { return get_nerf_scalar( CONST_REF_EARN_LESS_MONEY ); }
prestige_getWeaponDamageScalar() { return get_nerf_scalar( CONST_REF_LOWER_WEAPON_DAMAGE ); }
prestige_getNoClassAllowed() { return get_nerf_scalar( CONST_REF_NO_CLASS_ALLOWED ); }
prestige_getPistolsOnly() { return get_nerf_scalar( CONST_REF_PISTOLS_ONLY ); }
prestige_getSlowHealthRegenScalar() { return get_nerf_scalar( CONST_REF_SLOW_HEALTH_REGEN ); }
prestige_getMoveSlowScalar() { return get_nerf_scalar( CONST_REF_MOVE_SLOWER ); }
prestige_getNoAbilities() { return get_nerf_scalar( CONST_REF_NO_ABILITIES ); }
prestige_getMinAmmo() { return get_nerf_scalar( CONST_REF_MIN_AMMO ); }
prestige_getNoDeployables() { return get_nerf_scalar( CONST_REF_NO_DEPLOYABLES ); }

View File

@ -0,0 +1,677 @@
#include common_scripts\utility;
#include maps\mp\_utility;
#include maps\mp\alien\_utility;
#include maps\mp\agents\_agent_utility;
#include maps\mp\alien\_persistence;
MAX_CURRENCY = 6000;
ACTION_SLOT_MAX_FREQUENCY = 0.2;
main()
{
// init perks from data table
maps\mp\alien\_perks::init_perks();
// init combat resources from data table
maps\mp\alien\_combat_resources::init_combat_resources();
}
//=== Common ===
player_setup()
{
self SetActionSlot( 1, "" );
self SetActionSlot( 2, "" );
self SetActionSlot( 3, "" );
self SetActionSlot( 4, "" );
self NotifyOnPlayerCommand( "action_slot_1", "+actionslot 1" );
self NotifyOnPlayerCommand( "action_slot_2", "+actionslot 2" );
self NotifyOnPlayerCommand( "action_slot_3", "+actionslot 3" );
self NotifyOnPlayerCommand( "action_slot_4", "+actionslot 4" );
self NotifyOnPlayerCommand( "action_slot_1", "+actionslot 5" );
self NotifyOnPlayerCommand( "action_slot_2", "+actionslot 6" );
self NotifyOnPlayerCommand( "action_slot_3", "+actionslot 7" );
self NotifyOnPlayerCommand( "action_use", "+attack");
self NotifyOnPlayerCommand( "action_use", "+attack_akimbo_accessible");
self NotifyOnPlayerCommand( "change_weapon", "weapnext");
self thread player_watcher();
}
player_watcher()
{
if ( can_use_munition() )
{
self thread player_action_slot( level.alien_combat_resources[ "munition" ][ self get_selected_dpad_up() ], ::get_dpad_up_level, "action_slot_1" );
self thread player_action_slot( level.alien_combat_resources[ "support" ][ self get_selected_dpad_down() ], ::get_dpad_down_level, "action_slot_2" );
}
if ( can_use_ability() )
{
self thread player_action_slot( level.alien_combat_resources[ "defense" ][ self get_selected_dpad_left() ], ::get_dpad_left_level, "action_slot_3" );
self thread player_action_slot( level.alien_combat_resources[ "offense" ][ self get_selected_dpad_right() ], ::get_dpad_right_level, "action_slot_4" );
}
self thread player_watch_upgrade();
if ( !is_chaos_mode() )
self thread player_watch_currency_transfer();
}
can_use_munition()
{
if ( is_chaos_mode() )
return false;
if ( self maps\mp\alien\_prestige::prestige_getNoDeployables() == 1.0 )
return false;
return true;
}
can_use_ability() //checks the nerf_no_abilities and allows or disallows the left and right abilities
{
if ( self maps\mp\alien\_prestige::prestige_getNoAbilities() == 1.0 )
return false;
return true;
}
player_watch_upgrade()
{
self thread player_watch_dpad_upgrade( level.alien_combat_resources[ "munition" ][ self get_selected_dpad_up() ] );
self thread player_watch_dpad_upgrade( level.alien_combat_resources[ "support" ][ self get_selected_dpad_down() ] );
self thread player_watch_dpad_upgrade( level.alien_combat_resources[ "defense" ][ self get_selected_dpad_left() ] );
self thread player_watch_dpad_upgrade( level.alien_combat_resources[ "offense" ][ self get_selected_dpad_right() ] );
self thread player_watch_perk_upgrade( level.alien_perks["perk_0"][ self get_selected_perk_0() ], "perk_0" );
self thread player_watch_perk_upgrade( level.alien_perks["perk_1"][ self get_selected_perk_1() ], "perk_1" );
}
player_watch_dpad_upgrade( resource )
{
self player_watch_upgrade_internal( resource, resource.type );
}
player_watch_perk_upgrade( resource, slot )
{
self thread player_watch_upgrade_internal( resource, slot );
self thread player_handle_perk_upgrades( resource, slot );
}
player_watch_upgrade_internal( resource, type )
{
self endon( "disconnect" );
level endon( "game_ended" );
notifyname = type + "_try_upgrade";
while( true )
{
self waittillmatch( "luinotifyserver", notifyname );
rank = self get_upgrade_level( type );
if ( (rank + 1 < resource.upgrades.size) && self try_take_player_points( resource.upgrades[rank + 1].point_cost ) )
{
rank += 1;
self set_upgrade_level( type, rank );
self notify( "upgrade_" + type );
// track upgrades
self thread update_resource_stats( "upgrade", resource.ref, 1 );
maps\mp\alien\_alien_matchdata::record_perk_upgrade( resource.ref );
// ============ BBPRINT for combat resource upgrade =============
cyclenum = -1;
if ( isdefined( level.current_cycle_num ) )
cyclenum = level.current_cycle_num;
playername = "unknown";
if ( isdefined( self.name ) )
playername = self.name;
hivename = "unknown";
if ( isdefined( level.current_hive_name ) )
hivename = level.current_hive_name;
/#
if ( GetDvarInt( "alien_bbprint_debug" ) > 0 )
{
IPrintLnBold( "^8bbprint: aliencombatresourceupgraded \n" +
" cyclenum=" + cyclenum +
" hivename=" + hivename +
" resource=" + resource.ref +
" resourcelevel=" + rank +
" ownername=" + playername );
}
#/
bbprint( "aliencombatresourceupgraded",
"cyclenum %i hivename %s resource %s resourcelevel %s ownername %s ",
cyclenum,
hivename,
resource.ref,
rank,
playername );
// ============ BBPRINT for combat resource usage [END] =============
}
}
}
//=== Perks ===
get_perk_ref_at_upgrade_level( perk_type, perk_ref, upgrade_level )
{
return ( level.alien_perks[ perk_type ][ perk_ref ].upgrades[ upgrade_level ].ref );
}
player_handle_perk_upgrades( resource, type )
{
self endon( "disconnect" );
level endon( "game_ended" );
while ( true )
{
self waittill( "upgrade_" + type );
rank = self get_upgrade_level( type );
assert( rank > 0 );
unset_perk( get_perk_ref_at_upgrade_level( type, resource.ref, rank - 1 ) );
set_perk( get_perk_ref_at_upgrade_level( type, resource.ref, rank ) );
//kind of hacky, but this is probably the best place to piggyback for the secondary class upgrade
secondaryPerk = get_selected_perk_0_secondary();
if ( type == "perk_0" && secondaryPerk != "perk_none" )
{
secondaryResource = level.alien_perks["perk_0"][ secondaryPerk ];
unset_perk( get_perk_ref_at_upgrade_level( type, secondaryResource.ref, rank - 1 ) );
set_perk( get_perk_ref_at_upgrade_level( type, secondaryResource.ref, rank ) );
}
}
}
restore_all_perks()
{
perK_0_ref = self get_selected_perk_0();
perk_0_level = self get_perk_0_level();
set_perk( get_perk_ref_at_upgrade_level( "perk_0", perK_0_ref, perk_0_level ) );
secondaryPerk = get_selected_perk_0_secondary();
if ( secondaryPerk != "perk_none" )
{
secondaryResource = level.alien_perks["perk_0"][ secondaryPerk ];
set_perk( get_perk_ref_at_upgrade_level( "perk_0", secondaryResource.ref, perk_0_level ) );
}
}
//=== Action ===
player_cancel()
{
self player_cancel_internal();
//cleanup
self EnableWeapons( );
// Don't think we need this as it was definately switching the riotshield back to the pistol quickly when that was not intended. Put all last.weapon switching directly into the use callback.
// if ( IsDefined( self.last_weapon ) )
// self SwitchToWeapon( self.last_weapon );
self.alien_used_resource = undefined;
}
player_cancel_internal()
{
self endon( "player_action_slot_restart" );
self endon( "fired_ability_gun" );
self waittill_any( "change_weapon", "action_slot_1", "action_slot_2", "action_slot_3", "action_slot_4" ,"last_stand", "dpad_cancel" );
if ( self is_holding_deployable() && !self.is_holding_crate_marker )
{
// special case for escape chopper, cancels whatever you have in your hand
if ( !isdefined ( self.playerLinkedToChopper ) || !self.playerLinkedToChopper )
{
self.deployable = false;
self notify( "cancel_deployable_via_marker" );
if ( !self HasWeapon( "mortar_detonator_mp" ) && !self HasWeapon( "switchblade_laptop_mp" ) ) //special case for the mortar clacker and laptop, these need to get taken away from the player
self notify( "player_action_slot_restart" );
}
}
resource = self.alien_used_resource;
rank = self.alien_used_resource_rank;
self [[resource.callbacks.CancelUse]]( resource, rank );
self notify( "player_action_slot_restart" );
}
player_watch_use()
{
self endon( "cancel_watch" );
self waittill( "action_use" );
return true;
}
player_watch_riotshield_use( resource, rank )
{
self endon( "cancel_watch" );
self _disableUsability();
self thread reenable_usability( 3.1 );
self waittill_any_timeout( 3, "action_use", "riotshield_block", "riotshield_melee" );
if ( self player_has_enough_currency( Ceil( resource.upgrades[rank].cost ) ) )
return true;
else
{
self [[resource.callbacks.CancelUse]]( resource, rank );
self notify( "action_finish_used" );
self notify( "player_action_slot_restart" );
return false;
}
}
player_watch_equalizer_use( resource, rank )
{
self endon( "cancel_watch" );
self waittill_any_timeout( 3, "action_use" );
if ( self player_has_enough_currency( Ceil( resource.upgrades[rank].cost ) ) )
return true;
else
{
self [[resource.callbacks.CancelUse]]( resource, rank );
self notify( "action_finish_used" );
self notify( "player_action_slot_restart" );
return false;
}
}
player_watch_use_manned_turret()
{
self endon( "cancel_watch" );
while ( 1 )
{
self waittill( "action_use" );
if ( isDefined ( self.carriedSentry ) )
{
if ( is_true ( self.carriedSentry.canbeplaced ) )
return true;
}
}
}
player_watch_use_ims()
{
self endon( "disconnect" );
self endon( "cancel_watch" );
self waittill( "IMS_placed" );
return true;
}
player_watch_use_sentry()
{
self endon( "disconnect" );
self endon( "cancel_watch" );
assertex( isdefined( self.current_sentry ), "Sentry ent not set on owner holding it" );
for( ;; )
{
self waittill( "action_use" );
if ( isdefined( self.current_sentry ) )
{
canBePlaced = self maps\mp\alien\_autosentry_alien::can_place_sentry( self.current_sentry );
if ( canBePlaced )
return true;
}
wait ( 0.05 );
}
}
player_use( resource, rank )
{
// self.last_weapon = self GetCurrentWeapon();
self endon( "player_action_slot_restart" );
self endon( "disconnect" );
level endon( "game_ended" );
self thread player_cancel();
self [[resource.callbacks.TryUse]]( resource, rank );
if( self [[resource.callbacks.CanUse]]( resource ) )
{
if ( !show_alternate_spend_hint( resource ) ) //these already have a use hint, just need to show how to cancel
self thread maps\mp\alien\_hud::createSpendHintHUD( resource, rank );
else
self thread maps\mp\alien\_hud::createSpendHintHUD( resource, rank , &"ALIENS_PATCH_CANCEL_USE" );
usage = wait_for_use( resource, rank );
if ( !isDefined ( usage ) || !usage )
{
return;
}
if ( !self player_has_enough_currency( Ceil( resource.upgrades[rank].cost ) ) )
{
self notify("dpad_cancel" );
return;
}
self PlayLocalSound( "alien_killstreak_equip" );
self thread [[resource.callbacks.Use]]( resource, rank );
// track resource usage
self thread update_resource_stats( "purchase", resource.ref, 1 );
self take_player_currency( Ceil( resource.upgrades[rank].cost ), false, "ability" );
self.alien_used_resource = undefined;
// ============ BBPRINT for combat resource usage =============
cyclenum = -1;
if ( isdefined( level.current_cycle_num ) )
cyclenum = level.current_cycle_num;
playername = "unknown";
if ( isdefined( self.name ) )
playername = self.name;
hivename = "unknown";
if ( isdefined( level.current_hive_name ) )
hivename = level.current_hive_name;
/#
if ( GetDvarInt( "alien_bbprint_debug" ) > 0 )
{
IPrintLnBold( "^8bbprint: aliencombatresourceused \n" +
" cyclenum=" + cyclenum +
" hivename=" + hivename +
" resource=" + resource.ref +
" resourcelevel=" + rank +
" ownername=" + playername );
}
#/
bbprint( "aliencombatresourceused",
"cyclenum %i hivename %s resource %s resourcelevel %s ownername %s ",
cyclenum,
hivename,
resource.ref,
rank,
playername );
// ============ BBPRINT for combat resource usage [END] =============
self notify( "action_finish_used" );
self notify( "player_action_slot_restart" );
}
}
show_alternate_spend_hint( resource )
{
//check for maaws rocket on certain maps
if(level_uses_MAAWS() && IsSubStr( resource.ref,"predator" ))
return true;
return ( IsSubStr( resource.ref,"turret" ) || isSubStr( resource.ref, "_ims") );
}
wait_for_use( resource, rank )
{
switch ( resource.ref )
{
case "dpad_sentry":
return player_watch_use_sentry();
case "dpad_minigun_turret":
case "dpad_gl_sentry":
return player_watch_use_manned_turret();
case "dpad_ims":
return player_watch_use_ims();
case "dpad_team_ammo_reg":
case "dpad_team_armor":
case "dpad_team_boost":
case "dpad_team_adrenaline":
case "dpad_team_explosives":
case "dpad_team_randombox":
case "dpad_team_ammo_stun":
case "dpad_team_ammo_explo":
case "dpad_team_ammo_ap":
case "dpad_team_ammo_in":
case "dpad_placeholder_ammo_2":
return player_watch_box_thrown();
case "dpad_riotshield":
return player_watch_riotshield_use( resource, rank );
case "dpad_war_machine":
case "dpad_death_machine":
return player_watch_equalizer_use( resource, rank );
case "dpad_predator":
//if not maaws, just do the default
if(level_uses_MAAWS())
return player_watch_equalizer_use( resource, rank );
default:
return player_watch_use();
}
}
player_watch_box_thrown()
{
self endon( "cancel_watch" );
while ( true )
{
self waittill( "grenade_fire", item_thrown, weapon_name );
if ( weapon_name == "aliendeployable_crate_marker_mp" )
return true;
}
}
player_action_slot_internal( resource, get_rank_func, waittillname )
{
self endon( "player_action_slot_block" );
self endon( "disconnect" );
level endon( "game_ended" );
while ( true )
{
self waittill( waittillname );
if ( is_true ( self.player_action_disabled ) )
{
continue;
}
if ( self UseButtonPressed() ) //can't hold use button at the same time as pressing a dpad button or bad things can happen
continue;
if ( self IsOnLadder() )
continue;
if ( self has_special_weapon() )
{
self setLowerMessage( "cant_buy", &"ALIEN_COLLECTIBLES_PLAYER_HAS_SPECIALWEAPON", 3 );
continue;
}
if ( is_true ( self.picking_up_item ) )
{
continue;
}
if ( self IsUsingTurret() )
{
continue;
}
if ( is_true ( self.hasprogressbar ) )
{
continue;
}
if ( is_true ( self.isCarrying ) )
{
continue;
}
if ( isDefined ( self.throwingGrenade ) )
{
continue;
}
if ( flag_exist( "escape_conditions_met" ) && flag ( "escape_conditions_met" ) )
continue;
rank = self [[get_rank_func]]();
if ( !self player_has_enough_currency( Ceil( resource.upgrades[rank].cost ) ) )
{
continue;
}
self _DisableUsability();
self thread reenable_usability();
if ( !IsDefined( self.alien_used_resource ) )
{
if ( self [[resource.callbacks.CanPurchase]]( resource, rank ) )
{
self.alien_used_resource = resource;
self.alien_used_resource_rank = rank;
self thread player_use( resource, rank );
self notify( "player_action_slot_block" );
}
}
}
}
reenable_usability( wait_time )
{
self endon( "disconnect" );
if( !isDefined( wait_time ) )
wait_time = 1;
wait ( wait_time );
self _enableUsability();
}
player_action_slot( resource, get_dpad_level_func, dpad_notify_name )
{
self endon( "disconnect" );
level endon( "game_ended" );
while( true )
{
self thread player_action_slot_internal( resource, get_dpad_level_func, dpad_notify_name );
self waittill( "player_action_slot_restart" );
wait ACTION_SLOT_MAX_FREQUENCY;
}
}
// ========== Player currency transfer ============
player_watch_currency_transfer()
{
// self is player
self endon( "disconnect" );
level endon( "game_ended" );
wait 0.05;
if ( isPlayingSolo() )
return;
currency_rank = 0;
while ( 1 )
{
// allow drop of health pack
if ( self is_drop_button_pressed() )
{
// wait for release
hold_time = 2;
while ( self is_drop_button_pressed() && hold_time >= 0 )
{
wait 0.05;
hold_time -= 0.05;
}
if ( hold_time > 0 )
{
wait 0.05;
continue;
}
// drop money!
assertex( isdefined( level.deployable_currency_ranks[ currency_rank ] ), "Rank out of bound" );
if ( self player_has_enough_currency( level.deployable_currency_ranks[ currency_rank ] ) )
{
self deploy_currency( currency_rank );
level notify( "currency_dropped", self );
}
// prevent repeated dropping of money
while ( self is_drop_button_pressed() )
wait 0.05;
}
wait 0.5;
}
}
is_drop_button_pressed()
{
if ( !isdefined( self ) || !isalive( self ) )
return false;
if ( isdefined( self.laststand ) && self.laststand )
return false;
pressed_button_1 = self AdsButtonPressed();
pressed_button_2 = self JumpButtonPressed();
return pressed_button_1 && pressed_button_2;
}
deploy_currency( currency_rank )
{
// self is player who drops this
self endon( "disconnect" );
self notify( "deploying_currency" );
assertex( isdefined( level.deployable_currency_ranks[ currency_rank ] ), "Rank out of bound" );
self take_player_currency( level.deployable_currency_ranks[ currency_rank ],true );
boxType = "deployable_currency";
// only one time use
self.team_currency_rank = currency_rank;
maxUses = level.boxSettings[ boxType ].maxUses; // store old maxUses for restoring later
level.boxSettings[ boxType ].maxUses = 1; // override with 1
box = maps\mp\alien\_deployablebox::createBoxForPlayer( boxType, self.origin , self );
level.boxSettings[ boxType ].maxUses = maxUses; // restore
box.upgrade_rank = currency_rank;
box playSoundToPlayer( level.boxSettings[ boxType ].deployedSfx, self );
self thread currency_box_think( box );
}
currency_box_think( box )
{
// self is player
self endon( "disconnect" );
box endon( "death" );
wait 0.05;
box thread maps\mp\alien\_deployablebox::box_setActive( true );
// waittill deploying new box, remove old box if exist
self waittill( "deploying_currency" );
if ( isdefined( box ) )
box maps\mp\alien\_deployablebox::box_leave();
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,360 @@
#include maps\mp\_utility;
#include maps\mp\gametypes\_hud_util;
#include common_scripts\utility;
//============================================
// constants
//============================================
CONST_DRONE_HIVE_DEBUG = false;
CONST_MISSILE_COUNT = 0;
//============================================
// init
//============================================
init()
{
level.killstreakFuncs["drone_hive"] = ::tryUseDroneHive;
level.droneMissileSpawnArray = GetEntArray( "remoteMissileSpawn", "targetname" );
foreach( missileSpawn in level.droneMissileSpawnArray )
{
missileSpawn.targetEnt = GetEnt( missileSpawn.target, "targetname" );
}
}
//============================================
// tryUseDroneHive
//============================================
tryUseDroneHive( rank, num_missiles, missile_name, altitude, baby_missile_name )
{
/#
if( (!IsDefined(level.droneMissileSpawnArray) || !level.droneMissileSpawnArray.size) )
{
AssertMsg( "map needs remoteMissileSpawn entities" );
}
#/
self notify( "action_use" );
level thread maps\mp\alien\_music_and_dialog::PlayVOForPredator( self );
return useDroneHive( self, rank, num_missiles, missile_name, altitude, baby_missile_name );
}
//============================================
// useDroneHive
//============================================
useDroneHive( player, rank, num_missiles, missile_name, altitude, baby_missile_name )
{
player setUsingRemote( "remotemissile" );
self VisionSetNakedForPlayer( "black_bw", 0.75 );
self maps\mp\alien\_utility::restore_client_fog( 0 );
self thread set_visionset_for_watching_players( "black_bw", 0.75, 1.0 );
//blackOutWait = self waittill_any_timeout( 0.2, "disconnect", "death" );
level thread runDroneHive( player, rank, num_missiles, missile_name, altitude, baby_missile_name );
// level thread monitorDisownKillstreaks( player );
level thread monitorGameEnd( player, rank );
return true;
}
//============================================
// useDroneHive
//============================================
runDroneHive( player, rank, num_missiles, missile_name, altitude, baby_missile_name )
{
player endon( "killstreak_disowned" );
level endon( "game_ended" );
if ( !IsDefined( missile_name ) )
missile_name = "switchblade_rocket_mp";
if ( !IsDefined( num_missiles ) )
num_missiles = 0;
player notifyOnPlayerCommand( "missileTargetSet", "+attack" );
remoteMissileSpawn = getClosest( player.origin,level.droneMissileSpawnArray );
startPos = remoteMissileSpawn.origin;
targetPos = player.origin;
vector = VectorNormalize( startPos - targetPos );
startPos = ( vector * altitude ) + targetPos;
/#
if( CONST_DRONE_HIVE_DEBUG )
{
level thread drawLine( startPos, targetPos, 15, (1,0,0) );
}
#/
rocket = MagicBullet( missile_name, startpos, targetPos, player );
rocket SetCanDamage( true );
if( num_missiles != 0 )
rocket DisableMissileBoosting();
rocket.team = player.team;
rocket.type = "remote";
rocket.owner = player;
rocket.entityNumber = rocket GetEntityNumber();
level.rockets[ rocket.entityNumber ] = rocket;
level.remoteMissileInProgress = true;
level thread monitorDeath( rocket );
level thread monitorBoost( rocket );
missileEyes( player, rocket, rank );
// player setDepthOfField( 0, 96, 768, 4000, 4, 0 );
player notify( "action_use" );
player SetClientOmnvar( "ui_predator_missile", 1 );
missileCount = 0;
while( true )
{
result = rocket waittill_any_return( "death", "missileTargetSet" );
if( result == "death" )
break;
if ( missileCount < num_missiles )
{
level thread spawnSwitchBlade( rocket, missileCount, baby_missile_name );
missileCount++;
}
if( missileCount == num_missiles )
rocket EnableMissileBoosting();
}
player.turn_off_class_skill_activation = undefined;
returnPlayer( player, rank );
}
//============================================
// getEnemyTargets
//============================================
getEnemyTargets( owner )
{
enemyTargets = [];
foreach ( agent in level.agentArray )
{
// only active
if ( !IsDefined( agent.isActive ) || !agent.isActive )
continue;
enemyTargets[ enemyTargets.size ] = agent;
}
return enemyTargets;
}
//============================================
// spawnSwitchBlade
//============================================
spawnSwitchBlade( rocket, spawnOnLeft, baby_missile_name )
{
rocket.owner playLocalSound( "ammo_crate_use" );
forwardDir = AnglesToForward( rocket.angles );
rightDir = AnglesToRight( rocket.angles );
spawnOffset = (35,35,35);
targetOffset = (15000,15000,15000);
if(spawnOnLeft)
spawnOffset = spawnOffset * -1;
result = BulletTrace( rocket.origin, rocket.origin + (forwardDir * targetOffset), false, rocket );
targetOffset = targetOffset * result["fraction"];
startPoistion = rocket.origin + (rightDir * spawnOffset );
targetLocation = startPoistion + (forwardDir * targetOffset );
targets = rocket.owner getEnemyTargets( rocket.owner );
missile = MagicBullet( baby_missile_name, startPoistion, targetLocation, rocket.owner );
TargetArea = 262144; //512*512
foreach ( targ in targets )
{
if ( Distance2dsquared( targ.origin, targetLocation ) < TargetArea )
{
missile Missile_SetTargetEnt( targ );
break;
}
}
missile SetCanDamage( true );
missile.team = rocket.team;
missile.owner = rocket.owner;
missile.entityNumber = missile GetEntityNumber();
level.rockets[ missile.entityNumber ] = missile;
level thread monitorDeath( rocket );
}
//============================================
// getNextMissileSpawnIndex
//============================================
getNextMissileSpawnIndex( oldIndex )
{
index = oldIndex + 1;
if( index == level.droneMissileSpawnArray.size )
{
index = 0;
}
return index;
}
//============================================
// monitorBoost
//============================================
monitorBoost( rocket )
{
rocket endon( "death" );
while( true )
{
rocket.owner waittill( "missileTargetSet" );
rocket notify( "missileTargetSet" );
}
}
//============================================
// missileEyes
//============================================
missileEyes( player, rocket, rank )
{
delayTime = 1.0;
player freezeControlsWrapper( true );
if ( rank >= 1 )
player thread delayedFOFOverlay();
player CameraLinkTo( rocket, "tag_origin" );
player ControlsLinkTo( rocket );
player VisionSetMissilecamForPlayer( "default", delayTime );
player set_visionset_for_watching_players( "default", delayTime, undefined, true );
player VisionSetMissilecamForPlayer( game["thermal_vision_trinity"], 0.0 );
level thread unfreezeControls( player, delayTime );
}
delayedFOFOverlay()
{
self endon ( "death" );
self endon ( "disconnect" );
level endon ( "game_ended" );
maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( 0.25 );
self ThermalVisionFOFOverlayOn();
}
//============================================
// unfreezeControls
//============================================
unfreezeControls( player, delayTime, i )
{
player endon( "disconnect" );
wait( delayTime - 0.35 );
player freezeControlsWrapper( false );
}
//============================================
// monitorDisownKillstreaks
//============================================
monitorDisownKillstreaks( player, rank )
{
player endon( "end_kill_streak" );
player waittill( "killstreak_disowned" );
level thread returnPlayer( player, rank );
}
//============================================
// monitorGameEnd
//============================================
monitorGameEnd( player, rank )
{
player endon( "end_kill_streak" );
level waittill( "game_ended" );
level thread returnPlayer( player, rank );
}
//============================================
// monitorDeath
//============================================
monitorDeath( killStreakEnt )
{
killStreakEnt waittill( "death" );
level.rockets[ killStreakEnt.entityNumber ] = undefined;
level.remoteMissileInProgress = undefined;
}
//============================================
// returnPlayer
//============================================
returnPlayer( player, rank )
{
if( !IsDefined(player) )
return;
player SetClientOmnvar( "ui_predator_missile", 2 );
player notify( "end_kill_streak" );
player freezeControlsWrapper( true );
if ( rank >= 1 )
{
player ThermalVisionFOFOverlayOff();
}
player ControlsUnlink();
// player setDepthOfField( 0, 96, 768, 4000, 6, 1.8 );
player setExitPredatorVisionSet();
wait( 0.95 );
player CameraUnlink();
player SetClientOmnvar( "ui_predator_missile", 0 );
player clearUsingRemote();
if ( IsDefined( player.last_weapon ) )
player SwitchToWeapon( player.last_weapon );
}
setExitPredatorVisionSet()
{
transition_time = 0.5;
self VisionSetNakedForPlayer( "", transition_time );
self VisionSetStage( 0, transition_time );
}

2096
maps/mp/alien/_trap.gsc Normal file

File diff suppressed because it is too large Load Diff

140
maps/mp/alien/_unlock.gsc Normal file
View File

@ -0,0 +1,140 @@
// For the alien mode, certain unlocks are not based on the player's rank. This file keeps track of the in-game condition that
// will trigger those unlocks.
ALIEN_UNLOCK_TABLE = "mp/alien/unlocktable.csv";
TABLE_STARTING_ROW_INDEX = 100;
TABLE_END_ROW_INDEX = 110;
TABLE_INDEX = 0;
COLUMN_UNLOCK_ITEM = 1;
COLUMN_UNLOCK_TYPE = 3;
GOAL_ESCAPE = 1;
GOAL_ESCAPE_10_TIMES = 10;
GOAL_ESCAPE_20_TIMES = 20;
GOAL_ESCAPE_50_TIMES = 50;
init_unlock()
{
load_unlock_from_table();
}
init_player_unlock()
{
self.unlock_list = [];
if ( isDefined( level.unlock_registration_func ) )
[[level.unlock_registration_func]]();
if ( maps\mp\alien\_utility::is_true( level.include_default_unlocks ) )
register_default_unlocks();
}
register_default_unlocks()
{
register_unlock( "UNLOCK_ESCAPE" , 1, GOAL_ESCAPE , ::default_init );
register_unlock( "UNLOCK_ESCAPE_10_TIMES", 2, GOAL_ESCAPE_10_TIMES, ::default_init );
register_unlock( "UNLOCK_ESCAPE_20_TIMES", 3, GOAL_ESCAPE_20_TIMES, ::default_init );
register_unlock( "UNLOCK_ESCAPE_50_TIMES", 4, GOAL_ESCAPE_50_TIMES, ::default_init );
}
register_unlock( reference, index_map, goal, init_func )
{
unlock = spawnStruct();
unlock [[init_func]]( index_map, goal );
self.unlock_list[reference] = unlock;
}
default_init( index_map, goal )
{
self.progress = 0;
self.index_map = index_map;
self.goal = goal;
}
update_progress( progress_amount )
{
self.progress += progress_amount;
}
is_goal_achieved()
{
return ( self.progress >= self.goal );
}
is_valid_unlock( unlock )
{
return ( isDefined ( unlock ) );
}
update_unlock( reference, progress_amt )
{
unlock = self.unlock_list[reference];
if ( !is_valid_unlock( unlock ) )
return;
unlock update_progress( progress_amt );
if ( unlock is_goal_achieved() )
{
unlock_item_info = level.alien_unlock_data[unlock.index_map];
/#
maps\mp\alien\_debug::debug_print_item_unlocked( unlock_item_info.item, unlock_item_info.type );
#/
//self unlockAlienItem( unlock_item_info.item, unlock_item_info.type ); //<TODO J.C.> Waiting for real unlock code function here
}
}
update_escape_item_unlock( players_escaped )
{
foreach( player in players_escaped )
{
times_escaped = player maps\mp\alien\_persistence::get_player_escaped();
player update_personal_escape_item_unlock( times_escaped );
num_nerf_selected = player maps\mp\alien\_prestige::get_num_nerf_selected();
most_nerfs_escaped_with = player maps\mp\alien\_persistence::get_player_highest_nerf_escape_count();
if ( num_nerf_selected > most_nerfs_escaped_with )
{
player SetCoopPlayerData( "alienPlayerStats", "headShots", num_nerf_selected );
}
}
}
update_personal_escape_item_unlock( times_escaped )
{
update_unlock( "UNLOCK_ESCAPE" , 1 );
update_unlock( "UNLOCK_ESCAPE_10_TIMES", times_escaped );
update_unlock( "UNLOCK_ESCAPE_20_TIMES", times_escaped );
update_unlock( "UNLOCK_ESCAPE_50_TIMES", times_escaped );
}
load_unlock_from_table()
{
level.alien_unlock_data = [];
if ( isDefined ( level.alien_unlock_table ) )
unlock_table = level.alien_unlock_table;
else
unlock_table = ALIEN_UNLOCK_TABLE;
for ( rowIndex = TABLE_STARTING_ROW_INDEX; rowIndex <= TABLE_END_ROW_INDEX; rowIndex++ )
{
unlock_item = tableLookup( unlock_table, TABLE_INDEX, rowIndex, COLUMN_UNLOCK_ITEM );
if ( unlock_item == "" )
break;
unlock_type = tableLookup( unlock_table, TABLE_INDEX, rowIndex, COLUMN_UNLOCK_TYPE );
unlock_item_info = spawnStruct();
unlock_item_info.item = unlock_item;
unlock_item_info.type = unlock_type;
level.alien_unlock_data[level.alien_unlock_data.size] = unlock_item_info;
}
}

3670
maps/mp/alien/_utility.gsc Normal file

File diff suppressed because it is too large Load Diff