919 lines
31 KiB
Plaintext
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 );
|
|
}
|