iw6-scripts-dev/maps/mp/alien/_gamescore.gsc
2024-12-11 11:28:08 +01:00

919 lines
31 KiB
Plaintext

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