992 lines
27 KiB
Plaintext
992 lines
27 KiB
Plaintext
#using scripts\codescripts\struct;
|
|
|
|
#using scripts\shared\callbacks_shared;
|
|
#using scripts\shared\challenges_shared;
|
|
#using scripts\shared\drown;
|
|
#using scripts\shared\scoreevents_shared;
|
|
#using scripts\shared\system_shared;
|
|
#using scripts\shared\util_shared;
|
|
#using scripts\shared\weapons\_weapon_utils;
|
|
|
|
#using scripts\mp\_util;
|
|
#using scripts\mp\_challenges;
|
|
#using scripts\mp\gametypes\_globallogic;
|
|
#using scripts\mp\gametypes\_globallogic_score;
|
|
#using scripts\mp\gametypes\_loadout;
|
|
|
|
|
|
|
|
#using scripts\mp\_util;
|
|
|
|
|
|
|
|
|
|
// look for dvar loot_cryptokeyCost
|
|
// look for dvar loot_cryptokeyCost
|
|
|
|
|
|
|
|
|
|
// should coincide with contracts array size on mp_stats.ddl
|
|
|
|
|
|
|
|
// contract string table and columns
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// mp_stats.ddl, PlayerStatsList[ <stat_name> ]
|
|
// mp_stats.ddl, PlayerStatsList[ <stat_name> ]
|
|
// mp_stats.ddl
|
|
|
|
// table index values from mp_contractTable.csv
|
|
|
|
// weekly contracts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// daily contracts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// special contracts
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#namespace contracts;
|
|
|
|
#precache( "eventstring", "mp_daily_challenge_complete" );
|
|
#precache( "eventstring", "mp_weekly_challenge_complete" );
|
|
#precache( "eventstring", "mp_special_contract_complete" );
|
|
|
|
function autoexec __init__sytem__() { system::register("contracts",&__init__,undefined,undefined); }
|
|
|
|
function __init__()
|
|
{
|
|
callback::on_start_gametype( &start_gametype );
|
|
|
|
/# level thread watch_contract_debug(); #/
|
|
}
|
|
|
|
function start_gametype()
|
|
{
|
|
if ( !isdefined( level.ChallengesCallbacks ) )
|
|
{
|
|
level.ChallengesCallbacks = [];
|
|
}
|
|
|
|
util::init_player_contract_events(); // must always initialize
|
|
|
|
waittillframeend;
|
|
|
|
if ( can_process_contracts() )
|
|
{
|
|
/# execdevgui( "devgui/mp/mp_devgui_contracts" ); #/
|
|
|
|
challenges::registerChallengesCallback( "playerKilled",&contract_kills );
|
|
challenges::registerChallengesCallback( "gameEnd",&contract_game_ended );
|
|
globallogic_score::registerContractWinEvent( &contract_win );
|
|
scoreevents::register_hero_ability_kill_event( &on_hero_ability_kill );
|
|
scoreevents::register_hero_ability_multikill_event( &on_hero_ability_multikill );
|
|
scoreevents::register_hero_weapon_multikill_event( &on_hero_weapon_multikill );
|
|
|
|
util::register_player_contract_event( "score", &on_player_score, 1 );
|
|
util::register_player_contract_event( "killstreak_score", &on_killstreak_score, 2 );
|
|
util::register_player_contract_event( "offender_kill", &on_offender_kill );
|
|
util::register_player_contract_event( "defender_kill", &on_defender_kill );
|
|
util::register_player_contract_event( "headshot", &on_headshot_kill );
|
|
util::register_player_contract_event( "killed_hero_ability_enemy", &on_killed_hero_ability_enemy );
|
|
util::register_player_contract_event( "killed_hero_weapon_enemy", &on_killed_hero_weapon_enemy );
|
|
util::register_player_contract_event( "earned_specialist_ability_medal", &on_hero_ability_medal );
|
|
|
|
// globallogic::registerOtherLootXPAwards( &award_loot_xp ); // intentionally commented out, will use mp_loot_xp_due instead for now
|
|
}
|
|
|
|
callback::on_connect( &on_player_connect );
|
|
}
|
|
|
|
function on_killed_hero_ability_enemy()
|
|
{
|
|
self add_stat( 1014 );
|
|
}
|
|
|
|
function on_killed_hero_weapon_enemy()
|
|
{
|
|
self add_stat( 1014 );
|
|
}
|
|
|
|
function on_player_connect()
|
|
{
|
|
player = self;
|
|
|
|
if ( can_process_contracts() )
|
|
{
|
|
player setup_player_contracts();
|
|
}
|
|
}
|
|
|
|
function can_process_contracts()
|
|
{
|
|
if ( GetDvarInt( "contracts_enabled_mp", 1 ) == 0 ) // mp contracts kill switch
|
|
return false;
|
|
|
|
return challenges::canProcessChallenges();
|
|
}
|
|
|
|
function setup_player_contracts()
|
|
{
|
|
player = self;
|
|
|
|
player.pers["contracts"] = [];
|
|
|
|
// no need to setup active contracts for bots
|
|
if ( player util::is_bot() )
|
|
return;
|
|
|
|
for( slot = 0; slot < 10; slot++ )
|
|
{
|
|
if ( get_contract_stat( slot, "active" ) && !get_contract_stat( slot, "award_given" ) )
|
|
{
|
|
contract_index = get_contract_stat( slot, "index" );
|
|
player.pers["contracts"][contract_index] = SpawnStruct();
|
|
player.pers["contracts"][contract_index].slot = slot;
|
|
table_row = TableLookupRowNum( "gamedata/tables/mp/mp_contractTable.csv", 0, contract_index );
|
|
player.pers["contracts"][contract_index].table_row = table_row;
|
|
player.pers["contracts"][contract_index].target_value = int( TableLookupColumnForRow( "gamedata/tables/mp/mp_contractTable.csv", table_row, 2 ) );
|
|
player.pers["contracts"][contract_index].calling_card_stat = TableLookupColumnForRow( "gamedata/tables/mp/mp_contractTable.csv", table_row, 7 );
|
|
player.pers["contracts"][contract_index].weapon_camo_stat = TableLookupColumnForRow( "gamedata/tables/mp/mp_contractTable.csv", table_row, 8 );
|
|
player.pers["contracts"][contract_index].absolute_stat_path = TableLookupColumnForRow( "gamedata/tables/mp/mp_contractTable.csv", table_row, 9 );
|
|
}
|
|
}
|
|
}
|
|
|
|
/#
|
|
function watch_contract_debug()
|
|
{
|
|
level notify( "watch_contract_debug_singleton" );
|
|
level endon( "watch_contract_debug_singleton" );
|
|
|
|
level endon( "game_ended" );
|
|
|
|
while( 1 )
|
|
{
|
|
if ( GetDvarInt( "scr_contract_deactivate_all_slots" ) > 0 )
|
|
{
|
|
if ( isdefined( level.players ) )
|
|
{
|
|
new_index = GetDvarInt( "scr_contract_new_test_index", 0 );
|
|
|
|
foreach( player in level.players )
|
|
{
|
|
if ( !isdefined( player ) )
|
|
continue;
|
|
|
|
if ( player util::is_bot() )
|
|
continue;
|
|
|
|
for ( slot = 0; slot < 10; slot++ )
|
|
{
|
|
player set_contract_stat( slot, "active", 0 );
|
|
}
|
|
|
|
IPrintLn( "All contract slots deactivated for " + player.name );
|
|
|
|
player setup_player_contracts();
|
|
}
|
|
}
|
|
|
|
SetDvar( "scr_contract_deactivate_all_slots", 0 );
|
|
}
|
|
|
|
if ( GetDvarInt( "scr_contract_new_test_index", 0 ) > 0 )
|
|
{
|
|
if ( isdefined( level.players ) )
|
|
{
|
|
new_index = GetDvarInt( "scr_contract_new_test_index", 0 );
|
|
|
|
foreach( player in level.players )
|
|
{
|
|
if ( !isdefined( player ) )
|
|
continue;
|
|
|
|
if ( player util::is_bot() )
|
|
continue;
|
|
|
|
test_slot = GetDvarInt( "scr_contract_debug_slot", 10 - 1 );
|
|
|
|
player set_contract_stat( test_slot, "active", 1 );
|
|
player set_contract_stat( test_slot, "index", new_index );
|
|
player set_contract_stat( test_slot, "progress", 0 );
|
|
player set_contract_stat( test_slot, "award_given", 0 );
|
|
player setup_player_contracts();
|
|
|
|
IPrintLn( "Contract Slot " + test_slot + " table index set to " + new_index + " for " + player.name + ". Progress reset." );
|
|
}
|
|
}
|
|
|
|
SetDvar( "scr_contract_new_test_index", 0 );
|
|
}
|
|
|
|
if ( GetDvarInt( "scr_contract_deactivate_debug_slot", 0 ) > 0 )
|
|
{
|
|
if ( isdefined( level.players ) )
|
|
{
|
|
test_slot = GetDvarInt( "scr_contract_debug_slot", 10 - 1 );
|
|
IPrintLn( "Contract Debug Off" );
|
|
|
|
foreach( player in level.players )
|
|
{
|
|
if ( !isdefined( player ) )
|
|
continue;
|
|
|
|
if ( player util::is_bot() )
|
|
continue;
|
|
|
|
if ( test_slot >= 3 )
|
|
{
|
|
player set_contract_stat( test_slot, "active", 0 );
|
|
player setup_player_contracts();
|
|
|
|
IPrintLn( "Contract Slot " + test_slot + " deactivated for " + player.name );
|
|
}
|
|
else
|
|
{
|
|
IPrintLn( "Contract Slot " + test_slot + " left active for " + player.name );
|
|
}
|
|
}
|
|
}
|
|
|
|
SetDvar( "scr_contract_deactivate_debug_slot", 0 );
|
|
}
|
|
|
|
if ( GetDvarInt( "scr_contract_msg_front_end_only", 0 ) > 0 )
|
|
{
|
|
IPrintLn( "Assign Slot menu(s) only available in FrontEnd." );
|
|
SetDvar( "scr_contract_msg_front_end_only", 0 );
|
|
}
|
|
|
|
if ( GetDvarInt( "scr_contract_msg_debug_on", 0 ) > 0 )
|
|
{
|
|
IPrintLn( "Contracts Debug On. No slots altered." );
|
|
SetDvar( "scr_contract_msg_debug_on", 0 );
|
|
}
|
|
|
|
wait 0.5;
|
|
}
|
|
}
|
|
#/
|
|
|
|
function is_contract_active( challenge_index )
|
|
{
|
|
if ( !isPlayer( self ) )
|
|
return false;
|
|
|
|
if ( !isdefined( self.pers["contracts"] ) )
|
|
return false;
|
|
|
|
if ( !isdefined( self.pers["contracts"][challenge_index] ) )
|
|
return false;
|
|
|
|
// sanity check... better than causing an SRE
|
|
if ( self.pers["contracts"][challenge_index].table_row == -1 )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
function on_hero_ability_kill( ability, victimAbility )
|
|
{
|
|
player = self;
|
|
|
|
if ( !isdefined( player ) || !isplayer( player ) )
|
|
return;
|
|
}
|
|
|
|
function on_hero_ability_medal()
|
|
{
|
|
player = self;
|
|
|
|
if ( !isdefined( player ) || !isplayer( player ) )
|
|
return;
|
|
|
|
player add_stat( 1013 );
|
|
player add_stat( 3 );
|
|
}
|
|
|
|
function on_hero_ability_multikill( killcount, ability )
|
|
{
|
|
player = self;
|
|
|
|
if ( !isdefined( player ) || !isplayer( player ) )
|
|
return;
|
|
}
|
|
|
|
function on_hero_weapon_multikill( killcount, weapon )
|
|
{
|
|
player = self;
|
|
|
|
if ( !isdefined( player ) || !isplayer( player ) )
|
|
return;
|
|
}
|
|
|
|
function on_player_score( delta_score )
|
|
{
|
|
self add_stat( 1009, delta_score );
|
|
self add_stat( 5, delta_score );
|
|
}
|
|
|
|
function on_killstreak_score( delta_score, killstreak_purchased )
|
|
{
|
|
if ( killstreak_purchased )
|
|
{
|
|
self add_stat( 1011, delta_score );
|
|
}
|
|
}
|
|
|
|
function contract_kills( data )
|
|
{
|
|
victim = data.victim;
|
|
attacker = data.attacker;
|
|
player = attacker;
|
|
weapon = data.weapon;
|
|
time = data.time;
|
|
|
|
if ( !isdefined( weapon ) || ( weapon == level.weaponNone ) )
|
|
return;
|
|
|
|
if ( !isdefined( player ) || !isplayer( player ) )
|
|
return;
|
|
|
|
player add_stat( 1015 );
|
|
player add_stat( 4 );
|
|
|
|
if ( weapon.isHeroWeapon === true )
|
|
{
|
|
player add_stat( 1012 );
|
|
player add_stat( 7 );
|
|
player add_stat( 3006 );
|
|
}
|
|
|
|
isKillstreak = isdefined( data.eInflictor ) && isdefined( data.eInflictor.killstreakid );
|
|
if ( !isKillstreak && isdefined( level.isKillstreakWeapon ) )
|
|
{
|
|
isKillstreakWeapon = [[level.isKillstreakWeapon]]( weapon );
|
|
}
|
|
|
|
if ( isKillstreak || ( isKillstreakWeapon === true ) )
|
|
{
|
|
player add_stat( 1010 );
|
|
player add_stat( 8 );
|
|
}
|
|
|
|
statItemIndex = weapon.statIndex;
|
|
|
|
if ( player isItemPurchased( statItemIndex ) )
|
|
{
|
|
weaponClass = util::getWeaponClass( weapon );
|
|
|
|
switch ( weaponClass ) // aka group in mp_statsTable
|
|
{
|
|
case "weapon_assault":
|
|
player add_stat( 1019 );
|
|
player add_stat( 3001 );
|
|
break;
|
|
|
|
case "weapon_smg":
|
|
player add_stat( 1020 );
|
|
player add_stat( 3000 );
|
|
break;
|
|
|
|
case "weapon_sniper":
|
|
player add_stat( 1021 );
|
|
player add_stat( 3004 );
|
|
break;
|
|
|
|
case "weapon_lmg":
|
|
player add_stat( 1022 );
|
|
player add_stat( 3003 );
|
|
break;
|
|
|
|
case "weapon_cqb":
|
|
player add_stat( 1023 );
|
|
player add_stat( 3002 );
|
|
break;
|
|
|
|
case "weapon_pistol":
|
|
player add_stat( 1024 );
|
|
break;
|
|
|
|
case "weapon_knife":
|
|
player add_stat( 3005 );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
total_unlocked = player GetTotalUnlockedWeaponAttachments( weapon );
|
|
if ( total_unlocked >= 4 )
|
|
{
|
|
player add_stat( 1025 );
|
|
}
|
|
}
|
|
}
|
|
|
|
function add_stat( contract_index, delta )
|
|
{
|
|
if ( self is_contract_active( contract_index ) )
|
|
{
|
|
self add_active_stat( contract_index, delta );
|
|
}
|
|
}
|
|
|
|
function add_active_stat( contract_index, delta = 1 )
|
|
{
|
|
slot = self.pers["contracts"][contract_index].slot;
|
|
target_value = self.pers["contracts"][contract_index].target_value;
|
|
|
|
/#
|
|
if ( GetDvarInt( "scr_contract_debug_multiplier", 0 ) > 0 )
|
|
delta *= GetDvarInt( "scr_contract_debug_multiplier", 1 );
|
|
#/
|
|
|
|
old_progress = get_contract_stat( slot, "progress" );
|
|
new_progress = old_progress + delta;
|
|
|
|
if ( new_progress > target_value )
|
|
new_progress = target_value;
|
|
|
|
if ( new_progress != old_progress )
|
|
self set_contract_stat( slot, "progress", new_progress );
|
|
|
|
just_completed = false;
|
|
if ( old_progress < target_value && target_value <= new_progress )
|
|
{
|
|
just_completed = true;
|
|
|
|
// notify contract achieved
|
|
event = &"mp_weekly_challenge_complete";
|
|
display_rewards = false;
|
|
|
|
if ( slot == 2 )
|
|
{
|
|
event = &"mp_daily_challenge_complete";
|
|
display_rewards = true;
|
|
|
|
self award_loot_xp_due( award_daily_contract() );
|
|
self set_contract_stat( 2, "award_given", 1 );
|
|
}
|
|
else if ( slot == 0 || slot == 1 )
|
|
{
|
|
other_slot = 1;
|
|
if ( slot == 1 )
|
|
{
|
|
other_slot = 0;
|
|
}
|
|
|
|
foreach ( c_index,c_data in self.pers["contracts"] )
|
|
{
|
|
if ( c_data.slot == other_slot )
|
|
{
|
|
if ( c_data.target_value <= get_contract_stat( other_slot, "progress" ) )
|
|
{
|
|
display_rewards = true;
|
|
|
|
self award_loot_xp_due( award_weekly_contract() );
|
|
self set_contract_stat( 0, "award_given", 1 );
|
|
self set_contract_stat( 1, "award_given", 1 );
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if ( slot == 3 )
|
|
{
|
|
event = &"mp_special_contract_complete";
|
|
display_rewards = true;
|
|
|
|
absolute_stat_path = self.pers["contracts"][contract_index].absolute_stat_path;
|
|
if ( absolute_stat_path != "" )
|
|
{
|
|
set_contract_award_stat_from_path( absolute_stat_path, true );
|
|
}
|
|
|
|
calling_card_stat = self.pers["contracts"][contract_index].calling_card_stat;
|
|
if ( calling_card_stat != "" )
|
|
{
|
|
set_contract_award_stat( "calling_card", calling_card_stat );
|
|
}
|
|
|
|
weapon_camo_stat = self.pers["contracts"][contract_index].weapon_camo_stat;
|
|
if ( weapon_camo_stat != "" )
|
|
{
|
|
set_contract_award_stat( "weapon_camo", weapon_camo_stat );
|
|
}
|
|
|
|
self set_contract_stat( 3, "award_given", 1 );
|
|
}
|
|
|
|
/#
|
|
test_slot = GetDvarInt( "scr_contract_debug_slot", 10 - 1 );
|
|
if ( slot == test_slot )
|
|
{
|
|
if ( contract_index >= 1000 && contract_index <= 2999 )
|
|
{
|
|
event = &"mp_daily_challenge_complete";
|
|
}
|
|
display_rewards = true;
|
|
}
|
|
#/
|
|
|
|
self LUINotifyEvent( event, 2, contract_index, display_rewards );
|
|
}
|
|
|
|
/#
|
|
if ( GetDvarInt( "scr_contract_debug", 0 ) > 0 )
|
|
{
|
|
IPrintLn( "Contract Slot "+ slot + " table index " + contract_index + " progress: " + new_progress + "/" + target_value );
|
|
}
|
|
#/
|
|
}
|
|
|
|
function get_contract_stat( slot, stat_name )
|
|
{
|
|
return self GetDStat( "contracts", slot, stat_name );
|
|
}
|
|
|
|
function set_contract_stat( slot, stat_name, stat_value )
|
|
{
|
|
return self SetDStat( "contracts", slot, stat_name, stat_value );
|
|
}
|
|
|
|
function set_contract_award_stat( award_type, stat_name, stat_value = 1 )
|
|
{
|
|
// award_type is unused for now as we use PlayerStatsList for now
|
|
|
|
return self AddPlayerStat( stat_name, stat_value );
|
|
}
|
|
|
|
function set_contract_award_stat_from_path( stat_path, stat_value )
|
|
{
|
|
stat_path_array = StrTok( stat_path, " " );
|
|
|
|
string_path_1 = "";
|
|
string_path_2 = "";
|
|
string_path_3 = "";
|
|
string_path_4 = "";
|
|
string_path_5 = "";
|
|
|
|
switch( stat_path_array.size )
|
|
{
|
|
case 5:
|
|
string_path_5 = stat_path_array[4];
|
|
if( StrIsNumber( string_path_5 ) )
|
|
{
|
|
string_path_5 = Int( string_path_5 );
|
|
}
|
|
case 4:
|
|
string_path_4 = stat_path_array[3];
|
|
if( StrIsNumber( string_path_4 ) )
|
|
{
|
|
string_path_4 = Int( string_path_4 );
|
|
}
|
|
case 3:
|
|
string_path_3 = stat_path_array[2];
|
|
if( StrIsNumber( string_path_3 ) )
|
|
{
|
|
string_path_3 = Int( string_path_3 );
|
|
}
|
|
case 2:
|
|
string_path_2 = stat_path_array[1];
|
|
if( StrIsNumber( string_path_2 ) )
|
|
{
|
|
string_path_2 = Int( string_path_2 );
|
|
}
|
|
case 1:
|
|
string_path_1 = stat_path_array[0];
|
|
if( StrIsNumber( string_path_1 ) )
|
|
{
|
|
string_path_1 = Int( string_path_1 );
|
|
}
|
|
}
|
|
|
|
switch( stat_path_array.size )
|
|
{
|
|
case 1:
|
|
return self SetDStat( string_path_1, stat_value );
|
|
break;
|
|
case 2:
|
|
return self SetDStat( string_path_1, string_path_2, stat_value );
|
|
break;
|
|
case 3:
|
|
return self SetDStat( string_path_1, string_path_2, string_path_3, stat_value );
|
|
break;
|
|
case 4:
|
|
return self SetDStat( string_path_1, string_path_2, string_path_3, string_path_4, stat_value );
|
|
break;
|
|
case 5:
|
|
return self SetDStat( string_path_1, string_path_2, string_path_3, string_path_4, string_path_5, stat_value );
|
|
break;
|
|
default:
|
|
AssertMsg( "Stat path depth of " + stat_path_array.size + " is too large. Limit to 5 deep" );
|
|
break;
|
|
}
|
|
}
|
|
|
|
function award_loot_xp_due( amount )
|
|
{
|
|
if ( !isdefined( self ) )
|
|
return;
|
|
|
|
if ( amount <= 0 )
|
|
return;
|
|
|
|
current_amount = (isdefined(self GetDStat( "mp_loot_xp_due" ))?self GetDStat( "mp_loot_xp_due" ):0);
|
|
new_amount = current_amount + amount;
|
|
self SetDStat( "mp_loot_xp_due", new_amount );
|
|
}
|
|
|
|
function get_hero_weapon_mask( attacker, weapon )
|
|
{
|
|
if ( !isdefined( weapon ) )
|
|
return 0;
|
|
|
|
if ( isdefined( weapon.isHeroWeapon ) && !weapon.isHeroWeapon )
|
|
return 0;
|
|
|
|
switch( weapon.name )
|
|
{
|
|
case "hero_minigun":
|
|
case "hero_minigun_body3":
|
|
return 1; // note: heroWeaponMask needs to stay unique and consistent for function across TUs and FFOTDs
|
|
break;
|
|
case "hero_flamethrower":
|
|
return 1 << 1;
|
|
break;
|
|
case "hero_lightninggun":
|
|
case "hero_lightninggun_arc":
|
|
return 1 << 2;
|
|
break;
|
|
case "hero_chemicalgelgun":
|
|
case "hero_firefly_swarm":
|
|
return 1 << 3;
|
|
break;
|
|
case "hero_pineapplegun":
|
|
case "hero_pineapple_grenade":
|
|
return 1 << 4;
|
|
break;
|
|
case "hero_armblade":
|
|
return 1 << 5;
|
|
break;
|
|
case "hero_bowlauncher":
|
|
case "hero_bowlauncher2":
|
|
case "hero_bowlauncher3":
|
|
case "hero_bowlauncher4":
|
|
return 1 << 6;
|
|
break;
|
|
case "hero_gravityspikes":
|
|
return 1 << 7;
|
|
break;
|
|
case "hero_annihilator":
|
|
return 1 << 8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function get_hero_ability_mask( ability )
|
|
{
|
|
if ( !isdefined( ability ) )
|
|
return 0;
|
|
|
|
switch( ability.name )
|
|
{
|
|
case "gadget_clone":
|
|
return 1; // note: heroAbilityMask needs to stay unique and consistent for functions across TUs and FFOTDs
|
|
break;
|
|
case "gadget_heat_wave":
|
|
return 1 << 1;
|
|
break;
|
|
case "gadget_flashback":
|
|
return 1 << 2;
|
|
break;
|
|
case "gadget_resurrect":
|
|
return 1 << 3;
|
|
break;
|
|
case "gadget_armor":
|
|
return 1 << 4;
|
|
break;
|
|
case "gadget_camo":
|
|
return 1 << 5;
|
|
break;
|
|
case "gadget_vision_pulse":
|
|
return 1 << 6;
|
|
break;
|
|
case "gadget_speed_burst":
|
|
return 1 << 7;
|
|
break;
|
|
case "gadget_combat_efficiency":
|
|
return 1 << 8;
|
|
break;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function contract_game_ended( data )
|
|
{
|
|
// TODO: award challenge award here: maybe
|
|
}
|
|
|
|
function contract_win( winner )
|
|
{
|
|
winner add_stat( 1000 );
|
|
winner add_stat( 1 );
|
|
winner add_stat( 3007 );
|
|
winner add_stat( 3008 );
|
|
winner add_stat( 3009 );
|
|
winner add_stat( 3010 );
|
|
winner add_stat( 3011 );
|
|
winner add_stat( 3012 );
|
|
winner add_stat( 3013 );
|
|
winner add_stat( 3014 );
|
|
winner add_stat( 3015 );
|
|
winner add_stat( 3016 );
|
|
winner add_stat( 3017 );
|
|
winner add_stat( 3018 );
|
|
winner add_stat( 3019 );
|
|
winner add_stat( 3020 );
|
|
winner add_stat( 3021 );
|
|
winner add_stat( 3022 );
|
|
winner add_stat( 3023 );
|
|
winner add_stat( 3024 );
|
|
winner add_stat( 3025 );
|
|
winner add_stat( 3026 );
|
|
winner add_stat( 3027 );
|
|
winner add_stat( 3028 );
|
|
|
|
if ( util::is_objective_game( level.gametype ) )
|
|
{
|
|
winner add_stat( 2 );
|
|
}
|
|
|
|
if ( IsArenaMode() )
|
|
{
|
|
winner add_stat( 1001 );
|
|
}
|
|
|
|
gametype_win( winner );
|
|
}
|
|
|
|
function gametype_win( winner )
|
|
{
|
|
switch ( level.gametype )
|
|
{
|
|
case "tdm":
|
|
winner add_stat( 1002 );
|
|
break;
|
|
|
|
case "ball":
|
|
winner add_stat( 1003 );
|
|
break;
|
|
|
|
case "escort":
|
|
winner add_stat( 1004 );
|
|
break;
|
|
|
|
case "conf":
|
|
winner add_stat( 1005 );
|
|
break;
|
|
|
|
case "sd":
|
|
winner add_stat( 1006 );
|
|
break;
|
|
|
|
case "koth":
|
|
winner add_stat( 1007 );
|
|
break;
|
|
|
|
case "dom":
|
|
winner add_stat( 1008 );
|
|
break;
|
|
|
|
case "ctf":
|
|
winner add_stat( 1026 );
|
|
break;
|
|
|
|
case "dem":
|
|
winner add_stat( 1027 );
|
|
break;
|
|
|
|
case "dm":
|
|
winner add_stat( 1028 );
|
|
break;
|
|
|
|
case "clean":
|
|
winner add_stat( 1029 );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
function on_offender_kill()
|
|
{
|
|
self add_stat( 1018 );
|
|
self add_stat( 6 );
|
|
}
|
|
|
|
function on_defender_kill()
|
|
{
|
|
self add_stat( 1017 );
|
|
self add_stat( 6 );
|
|
}
|
|
|
|
function on_headshot_kill()
|
|
{
|
|
self add_stat( 1016, 1 );
|
|
}
|
|
|
|
function award_loot_xp()
|
|
{
|
|
player = self;
|
|
|
|
if ( !isdefined( player.pers["contracts"] ) )
|
|
return 0;
|
|
|
|
loot_xp = 0;
|
|
|
|
//
|
|
// daily contract
|
|
//
|
|
daily_slot = 2;
|
|
if ( get_contract_stat( daily_slot, "active" ) && !get_contract_stat( daily_slot, "award_given" ) )
|
|
{
|
|
if ( contract_slot_met( daily_slot ) )
|
|
{
|
|
loot_xp += player award_daily_contract();
|
|
player set_contract_stat( daily_slot, "award_given", 1 );
|
|
}
|
|
}
|
|
|
|
//
|
|
// weekly contract
|
|
//
|
|
weekly_slot_A = 0;
|
|
weekly_slot_B = 1;
|
|
if ( get_contract_stat( weekly_slot_A, "active" ) && !get_contract_stat( weekly_slot_A, "award_given" ) &&
|
|
get_contract_stat( weekly_slot_B, "active" ) && !get_contract_stat( weekly_slot_B, "award_given" ) )
|
|
{
|
|
if ( contract_slot_met( weekly_slot_A ) && contract_slot_met( weekly_slot_B ) )
|
|
{
|
|
loot_xp += player award_weekly_contract();
|
|
player set_contract_stat( weekly_slot_A, "award_given", 1 );
|
|
player set_contract_stat( weekly_slot_B, "award_given", 1 );
|
|
}
|
|
}
|
|
|
|
return loot_xp;
|
|
}
|
|
|
|
function contract_slot_met( slot )
|
|
{
|
|
player = self;
|
|
|
|
contract_index = get_contract_stat( slot, "index" );
|
|
|
|
if ( !isdefined( player.pers["contracts"][contract_index] ) )
|
|
return false;
|
|
|
|
progress = player get_contract_stat( slot, "progress" );
|
|
target_value = player.pers["contracts"][contract_index].target_value;
|
|
|
|
return ( progress >= target_value );
|
|
}
|
|
|
|
function award_daily_contract()
|
|
{
|
|
return GetDvarInt( "daily_contract_cryptokey_reward_count", 10 ) * GetDvarInt( "loot_cryptokeyCost", 100 );
|
|
}
|
|
|
|
function award_weekly_contract()
|
|
{
|
|
self award_blackjack_contract();
|
|
|
|
return GetDvarInt( "weekly_contract_cryptokey_reward_count", 30 ) * GetDvarInt( "loot_cryptokeyCost", 100 );
|
|
}
|
|
|
|
function award_blackjack_contract()
|
|
{
|
|
contract_count = self GetDStat( "blackjack_contract_count" );
|
|
reward_count = GetDvarInt( "weekly_contract_blackjack_contract_reward_count", 1 );
|
|
self SetDStat( "blackjack_contract_count", contract_count + reward_count );
|
|
}
|