#include common_scripts\utility;
#include maps\_utility;
#include maps\_hud_util;

/* -=-=-=-=-=-=-=-=-=-=

PMC & CO-OP Money system

-=-=-=-=-=-=-=-=-=-=-=- */

// constants
CONST_money_notify_interval			 = 5000;					// Email notifies every $2000 earned
CONST_money_kill					 = 100;
CONST_money_kill_melee				 = 150;
CONST_money_juggernaut_kill			 = 500;
CONST_money_juggernaut_kill_melee	 = 600;
CONST_money_objective				 = 500;
CONST_money_completion				 = 1000;
  
CONST_bonus_money_sound				 = "extra_money_reward";

CONST_lootSound 					 = "loot_drop_epic";
CONST_lootString 					 = "New mail!";
CONST_lootIcon 						 = "temp_mail_icon";
CONST_lootColor 					 = ( 0.55, 1, 0.55 );

init()
{
	maps\_hud::init();

	precacheshader( "line_horizontal" );
	precacheshader( "line_vertical" );
	precacheshader( "gradient_fadein" );
	precachemenu( "coop_eog_summary" );
	precachemenu( "coop_eog_summary2" );
	precachemenu( "sp_eog_summary" );

	level._reward[ "kill" ]					 = CONST_money_kill;
	level._reward[ "kill_melee" ]			 = CONST_money_kill_melee;
	level._reward[ "juggernaut_kill" ]		 = CONST_money_juggernaut_kill;
	level._reward[ "juggernaut_kill_melee" ]	 = CONST_money_juggernaut_kill_melee;
	level._reward[ "completion" ]			 = CONST_money_completion;

	thread setupLoot();
	thread money_setup();
	foreach ( player in level._players )
	{
		player thread money_player_init();
	}
}

money_player_init()
{
	if ( !isDefined( self.summary ) )
	{
		self.summary[ "summary" ] = [];
		self.summary[ "summary" ][ "intervals" ] = 0;
		self.summary[ "summary" ][ "completion" ] = 0;
		self.summary[ "summary" ][ "total_money" ] = 0;
		self.summary[ "summary" ][ "mission_start_time" ] = getTime();
	}

	self.moneyUpdateTotal = 0;
	self.hud_moneyupdate = newclientHudElem( self );
	self.hud_moneyupdate.horzAlign = "center";
	self.hud_moneyupdate.vertAlign = "middle";
	self.hud_moneyupdate.alignX = "center";
	self.hud_moneyupdate.alignY = "middle";
	self.hud_moneyupdate.x = 0;
	self.hud_moneyupdate.y = -60;
	self.hud_moneyupdate.font = "default";
	self.hud_moneyupdate.fontscale = 2;
	self.hud_moneyupdate.archived = false;
	self.hud_moneyupdate.color = ( 0.55, 1, 0.55 );
	self.hud_moneyupdate fontPulseInit();

	self.hud_totalmoney = newclientHudElem( self );
	self.hud_totalmoney.horzAlign = "right";
	self.hud_totalmoney.vertAlign = "top";
	self.hud_totalmoney.alignX = "right";
	self.hud_totalmoney.alignY = "top";
	self.hud_totalmoney.x = 0;
	self.hud_totalmoney.y = 0;
	self.hud_totalmoney.font = "default";
	self.hud_totalmoney.fontscale = 2;
	self.hud_totalmoney.archived = false;
	self.hud_totalmoney.color = ( 0.55, 1, 0.55 );
	self.hud_totalmoney.alpha = 0;
	self.hud_totalmoney.label = "";
	self.hud_totalmoney fontPulseInit();

	self thread initNotifyMessage();

	self thread show_total_money();
}

initNotifyMessage()
{
	if ( is_coop() )
	{
		titleSize = 2.5;
		textSize = 1.75;
		iconSize = 24;
		font = "objective";
		point = "TOP";
		relativePoint = "BOTTOM";
		yOffset = 30;
		xOffset = 0;
	}
	else
	{
		titleSize = 2.5;
		textSize = 1.75;
		iconSize = 30;
		font = "objective";
		point = "TOP";
		relativePoint = "BOTTOM";
		yOffset = 30;
		xOffset = 0;
	}

	self.notifyTitle = createClientFontString( font, titleSize );
	self.notifyTitle setPoint( point, undefined, xOffset, yOffset );
	self.notifyTitle.glowColor = ( 0.2, 0.3, 0.7 );
	self.notifyTitle.glowAlpha = 1;
	self.notifyTitle.hideWhenInMenu = true;
	self.notifyTitle.archived = false;
	self.notifyTitle.alpha = 0;

	self.notifyText = createClientFontString( font, textSize );
	self.notifyText setParent( self.notifyTitle );
	self.notifyText setPoint( point, relativePoint, 0, 0 );
	self.notifyText.glowColor = ( 0.2, 0.3, 0.7 );
	self.notifyText.glowAlpha = 1;
	self.notifyText.hideWhenInMenu = true;
	self.notifyText.archived = false;
	self.notifyText.alpha = 0;

	self.notifyText2 = createClientFontString( font, textSize );
	self.notifyText2 setParent( self.notifyTitle );
	self.notifyText2 setPoint( point, relativePoint, 0, 0 );
	self.notifyText2.glowColor = ( 0.2, 0.3, 0.7 );
	self.notifyText2.glowAlpha = 1;
	self.notifyText2.hideWhenInMenu = true;
	self.notifyText2.archived = false;
	self.notifyText2.alpha = 0;

	self.notifyIcon = createClientIcon( "white", iconSize, iconSize );
	self.notifyIcon setParent( self.notifyText2 );
	self.notifyIcon setPoint( point, relativePoint, 0, 0 );
	self.notifyIcon.hideWhenInMenu = true;
	self.notifyIcon.archived = false;
	self.notifyIcon.alpha = 0;

	self.doingNotify = false;
	self.notifyQueue = [];
}

show_total_money()
{
	// Shows total money the player has earned in the corner of the screen
	// Fades in when money is made, counts up, then fades out
	assert( isdefined( self.hud_totalmoney ) );

	currentCount = 0;
	moneyToAddPerFrame = 10;
	for ( ;; )
	{
		while ( self.summary[ "summary" ][ "total_money" ] == currentCount )
			wait 0.05;

		currentCount += moneyToAddPerFrame;
		if ( currentCount > self.summary[ "summary" ][ "total_money" ] )
			currentCount = self.summary[ "summary" ][ "total_money" ];

		self notify( "stop_total_money_fade" );
		self.hud_totalmoney.alpha = 1;
		self.hud_totalmoney setValue( currentCount );

		if ( self.summary[ "summary" ][ "total_money" ] == currentCount )
			self thread show_total_money_fadeout();

		wait 0.05;
	}
}

show_total_money_fadeout()
{
	self endon( "stop_total_money_fade" );
	//self.hud_totalmoney thread fontPulse( self );
	wait 3.0;
	self.hud_totalmoney fadeOverTime( 0.75 );
	self.hud_totalmoney.alpha = 0;
}

// returns bool if player's current money satisfies an email notification
money_mailNotify()
{
	// self is player
	cur_money = self.summary[ "summary" ][ "total_money" ];
	cur_emails = self.summary[ "summary" ][ "intervals" ];		// number of emails

	// notify condition A
	// send player email every CONST_money_notify_interval dollars
	if ( cur_emails < int( cur_money / CONST_money_notify_interval ) )
		self email_popup();
}

email_popup()
{
	giveLoot( self );
	//iprintln( self.summary[ "summary" ][ "intervals" ] + "th email" );
	self.summary[ "summary" ][ "intervals" ]++ ;
}

money_setup()
{
	// in dollars $$$
	registerMoneyType( "kill", CONST_money_kill );
	registerMoneyType( "kill_melee", CONST_money_kill_melee );
	registerMoneyType( "juggernaut_kill", CONST_money_juggernaut_kill );
	registerMoneyType( "juggernaut_kill_melee", CONST_money_juggernaut_kill_melee );
	registerMoneyType( "headshot", CONST_money_juggernaut_kill );
	registerMoneyType( "assist", 0 );
	registerMoneyType( "objective", CONST_money_objective );
	registerMoneyType( "completion", CONST_money_completion );
	registerMoneyType( "suicide", 0 );
	registerMoneyType( "teamkill", 0 );
}

giveMoney_think()
{
	self waittill( "death", attacker, type, weapon );
	// split for recursive call
	self giveMoney_helper( attacker, type );
}

giveMoney_helper( attacker, type )
{
	if ( isdefined( attacker ) && !isplayer( attacker ) )
	{
		if ( isdefined( self.saved_player_attacker ) )
			attacker = self.saved_player_attacker;
	}

	// if AI removed by script/game, no money to player
	if ( !isdefined( attacker ) )
		return;

	playBonusSound = false;
	juggernaut = false;
	killType = "kill";
	if ( isdefined( self.juggernaut ) )
	{
		killType = "juggernaut_kill";
		juggernaut = true;
		playBonusSound = true;
	}

	// Melee kills are worth more money cuz you're good like dat
	if ( ( isdefined( type ) ) && ( issubstr( tolower( type ), "melee" ) ) )
	{
		if ( juggernaut )
			killType = "juggernaut_kill_melee";
		else
			killType = "kill_melee";
		playBonusSound = true;
	}

	// if player is last to kill, give player kill points	
	if ( isPlayer( attacker ) )
	{
		if ( getdvar( "money_sharing" ) == "1" )
		{
			foreach ( player in level._players )
			{
				if ( isdefined( self.kill_reward_money ) )
				{
					if ( killType == "kill_melee" && isdefined( self.kill_melee_reward_money ) )
						player thread giveMoney( killType, self.kill_melee_reward_money, attacker );
					else
						player thread giveMoney( killType, self.kill_reward_money, attacker );
				}
				else
					player thread giveMoney( killType, undefined, attacker );
			}
		}
		else
			attacker thread giveMoney( killType );

		if ( playBonusSound )
			attacker playLocalSound( CONST_bonus_money_sound );

		return;
	}

	// no money if enemy was finished off by other enemies
	if ( isAI( attacker ) && attacker isBadGuy() )
		return;

	// if enemy shot by player was killed by destructibles
	if ( is_special_targetname_attacker( attacker ) )
	{
		if ( isdefined( attacker.attacker ) )
			self thread giveMoney_helper( attacker.attacker );
		return;
	}

	// if enemy shot by player was killed by natural causes, no money
	if ( !isPlayer( attacker ) && !isAI( attacker ) )
		return;

	/*
	// if enemy shot by player was killed by friendly, give assist
	if ( isdefined( self.attacker_list ) && self.attacker_list.size > 0 )
	{
		for ( i = 0; i < self.attacker_list.size; i++ )
		{
			// if attacker is player and not the last to kill, give player assist points
			if ( isPlayer( self.attacker_list[ i ] ) && self.attacker_list[ i ] != attacker )
				self.attacker_list[ i ] thread giveMoney( "assist" );
		}
	}
	*/
}

give_objective_reward()
{
	if ( getdvar( "money_sharing" ) == "1" )
	{
		foreach ( player in level._players )
			player giveMoney( "objective" );
	}
	else if ( isdefined( self ) && isPlayer( self ) )
		self giveMoney( "objective" );
	else
		level._player giveMoney( "objective" );
}


is_special_targetname_attacker( attacker )
{
	assert( isdefined( attacker ) );
	if ( !isdefined( attacker.targetname ) )
		return false;

	if ( attacker.targetname == "destructible" )
		return true;

	if ( string_starts_with( attacker.targetname, "sentry_" ) )
		return true;

	return false;
}

AI_money_init()
{
	self thread giveMoney_think();
	self.attacker_list = [];
	self.last_attacked = 0;
	self add_damage_function( ::took_damage );
}

took_damage( damage, attacker, direction_vec, point, type, modelName, tagName )
{
	if ( !isdefined( self ) )
	{
		// AI removed, no need to keep track
		return;
	}
		
	if ( !isdefined( attacker ) )
		return;

	// this is to make sure player gets money after killing enemy during their traversal anim
	if ( isplayer( attacker ) )
		self.saved_player_attacker = attacker;

	currentTime = gettime();
	timeElapsed = currentTime - self.last_attacked;
	if ( timeElapsed <= 10 * 3000 )	// 10 * 1000
	{
		self.attacker_list[ self.attacker_list.size ] = attacker;
		self.last_attacked = gettime();
		return;
	}

	self.attacker_list = [];
	self.attacker_list[ 0 ] = attacker;
	self.last_attacked = gettime();
}

// used by _utility.gsc, edit with care
updatePlayerMoney( type, value, attacker )
{
	self notify( "update_money" );
	self endon( "update_money" );

	if ( getdvar( "money_enable", "0" ) != "1" )
		return;

	// optional in game reward control
	if ( getdvar( "in_game_reward" ) != "1" )
	{
		allowed_types = "completion ";
		allowed_types_array = strTok( allowed_types, " " );

		//disabled_types = "kill kill_melee juggernaut_kill juggernaut_kill_melee headshot assist objective";
		//disabled_types_array = [];
		//disabled_types_array = strTok( disabled_types, " " );

		foreach ( s_type in allowed_types_array )
		{
			if ( type != s_type )
				return;
		}
	}

	if ( !isDefined( value ) )
	{
		if ( isDefined( level._scoreInfo[ type ] ) )
			value = getScoreInfoValue( type );
		else
			value = getScoreInfoValue( "kill" );
	}

	// update reward value trackers

	value = int( value );

	if ( !( type == "kill" || type == "kill_melee" || type == "headshot" ) )
		self.summary[ "summary" ][ "completion" ] += value;	// if custom reward type, it counts towards level completion
	else if ( type == "assist" )
	{
		// assist points can never add up over kill points
		if ( value > getScoreInfoValue( "kill" ) )
			value = getScoreInfoValue( "kill" );
	}

	self.moneyUpdateTotal += value;

	bShowMoneyUpdate = true;
	if ( isdefined( attacker ) && self != attacker )
		bShowMoneyUpdate = false;

	if ( bShowMoneyUpdate )
	{
		// $
		self.hud_moneyupdate.label = "";
		self.hud_moneyupdate setValue( self.moneyUpdateTotal );
		self.hud_moneyupdate.alpha = 0.65;
		self.hud_moneyupdate thread fontPulse( self );
	}

	wait 1;

	if ( bShowMoneyUpdate )
	{
		self.hud_moneyupdate fadeOverTime( 0.75 );
		self.hud_moneyupdate.alpha = 0;
	}

	self.summary[ "summary" ][ "total_money" ] += self.moneyUpdateTotal;

	self.moneyUpdateTotal = 0;

	// email notify
	self thread money_mailNotify();
}

fontPulseInit()
{
	self.baseFontScale = self.fontScale;
	self.maxFontScale = self.fontScale * 2;
	//self.moveUpSpeed = 1.25;
	self.inFrames = 3;
	self.outFrames = 5;
}


fontPulse( player )
{
	self notify( "fontPulse" );
	self endon( "fontPulse" );

	scaleRange = self.maxFontScale - self.baseFontScale;
	//self thread fontMoveup( -60 );

	while ( self.fontScale < self.maxFontScale )
	{
		self.fontScale = min( self.maxFontScale, self.fontScale + ( scaleRange / self.inFrames ) );
		wait 0.05;
	}

	while ( self.fontScale > self.baseFontScale )
	{
		self.fontScale = max( self.baseFontScale, self.fontScale - ( scaleRange / self.outFrames ) );
		wait 0.05;
	}
}

/*
fontMoveup( start )
{
	self endon( "fontPulse" );
	self.y = start;

	while ( abs( start ) - abs( self.y ) < 60 )
	{
		self.y = self.y - self.moveUpSpeed;
		wait 0.05;
	}
}*/

// ============== LOOT NOTIFY ================

giveLoot( attacker )
{
	if ( !isDefined( attacker.lootIcon ) )
	{
		attacker.lootIcon = attacker createIcon( "white", 32, 16 );
		attacker.lootIcon setPoint( "TOPRIGHT", undefined, getDvarFloat( "scr_loot_offsetX" ), getDvarFloat( "scr_loot_offsetY" ) );
		attacker.lootIcon.alpha = 0;
	}

	if ( !isDefined( attacker.lootString ) )
	{
		attacker.lootString = attacker createFontString( "default", 1.5 );
		attacker.lootString setParent( attacker.lootIcon );
		attacker.lootString setPoint( "RIGHT", "LEFT", 0, 0 );
		attacker.lootString setText( "ASDF" );
		attacker.lootString.glowColor = ( 1, 1, 1 );
		attacker.lootString.glowAlpha = 0;
		attacker.lootString.alpha = 0;
		attacker.lootString fontPulseInit();
	}

	if ( !isDefined( attacker.moneyString ) )
	{
		attacker.moneyString = attacker createFontString( "default", 2 );
		attacker.moneyString setParent( attacker.lootIcon );
		attacker.moneyString setPoint( "RIGHT", "LEFT", 0, 0 );
		attacker.moneyString setText( "ASDF" );
		attacker.moneyString.glowColor = ( 1, 1, 1 );
		attacker.moneyString.glowAlpha = 0;
		attacker.moneyString.alpha = 0;
		attacker.moneyString fontPulseInit();
	}

	attacker.lootIcon setPoint( "TOPRIGHT", undefined, getDvarFloat( "scr_loot_offsetX" ), getDvarFloat( "scr_loot_offsetY" ) );
	attacker.lootString setPoint( "RIGHT", "LEFT", -10, 0 );
	attacker.moneyString setPoint( "RIGHT", "LEFT", -10, 20 );
	attacker thread showLoot( CONST_lootString, CONST_lootIcon, CONST_lootSound, CONST_lootColor );
	attacker thread showMoney( attacker.summary[ "summary" ][ "total_money" ] );
}

showMoney( amount )
{
	self endon( "got_loot" );
	self endon( "disconnect" );

	self.moneyString setText( "$0" );
	self thread moneyCountUp( amount );
	self.moneyString.alpha = 1;
	self.moneyString.color = CONST_lootColor;

	if ( getDvarInt( "scr_loot_slowPrint" ) )
		self.moneyString setPulseFX( 100, int( getDvarFloat( "scr_loot_showTime" ) * 1000 ), 1000 );
	else
		self.moneyString thread fontPulse( self );

	wait( getDvarFloat( "scr_loot_showTime" ) );
	self.moneyString fadeOverTime( 1.0 );
	self.moneyString.alpha = 0;
}

moneyCountUp( amount )
{
	self endon( "got_loot" );
	self endon( "disconnect" );

	counts = 10;
	for ( i = counts; i > 0; i -- )
	{
		self.moneyString setText( "$" + int( amount / i ) );
		wait 0.1;
	}
}

showLoot( lootString, lootIcon, lootSound, lootColor )
{
	self notify( "got_loot" );
	self endon( "got_loot" );
	self endon( "disconnect" );

	wait( getDvarFloat( "scr_loot_dropDelay" ) );

	self playLocalSound( lootSound );

	self.lootString setText( lootString );
	self.lootString.alpha = 1;
	self.lootString.color = lootColor;

	if ( getDvarInt( "scr_loot_slowPrint" ) )
		self.lootString setPulseFX( 100, int( getDvarFloat( "scr_loot_showTime" ) * 1000 ), 1000 );
	else
		self.lootString thread fontPulse( self );

	self.lootIcon setIconShader( lootIcon );
	self.lootIcon.alpha = 1;
	wait( getDvarFloat( "scr_loot_showTime" ) );
	self.lootString fadeOverTime( 1.0 );
	self.lootString.alpha = 0;
	self.lootIcon fadeOverTime( 1.0 );
	self.lootIcon.alpha = 0;
}

setupLoot()
{
	precacheShader( "temp_mail_icon" );

	if ( getDvar( "scr_loot_dropDelay" ) == "" )
		setDvar( "scr_loot_dropDelay", 0.0 );

	if ( getDvar( "scr_loot_showTime" ) == "" )
		setDvar( "scr_loot_showTime", 7.0 );

	if ( getDvar( "scr_loot_offsetX" ) == "" )
		setDvar( "scr_loot_offsetX", 0 );

	if ( getDvar( "scr_loot_offsetY" ) == "" )
		setDvar( "scr_loot_offsetY", 0 );

	if ( getDvar( "scr_loot_slowPrint" ) == "" )
		setDvar( "scr_loot_slowPrint", 1 );
}


// ============== helpers ===============

registerMoneyType( type, value )
{
	level._scoreInfo[ type ][ "value" ] = value;
}

getScoreInfoValue( type )
{
	return( level._scoreInfo[ type ][ "value" ] );
}