//////////////////////////////////////////////////////////////////////////////////
//
//	DoD Shell Shock
//		- Version 0.9
//		- 06.11.2006
//		- diamond-optic (original code by v3x)
//
//////////////////////////////////////////////////////////////////////////////////
//
// Credit:
//
//   - Original Code by v3x (he_damage_effect v0.2)
//   - http://www.amxmodx.org/forums/viewtopic.php?t=25271
//   - Ported to DoD by diamond-optic
//   - cadav0r: fade & shake CVAR code, new volume fx method, and various other fixes
//   - WARDOG: new ringing sound
//
// Information:
//
//   - When you take damage from grenades or rockets, your
//     screen will be distorted & you're sound volume
//     will decrease for a few seconds before it returns
//     to normal. There is also a ringing sound thats played.
//     I dont really know how to best explain this....
//   - Minimum damage required is controlled by cvars
//     for each one of the effects...
//   - Each effect is also controlled by cvars (on/off)
//
//   - The fov effect isnt finished yet, therefor it defualts
//     to '0' (off) but I left the code here incase anyone
//     else wants to play around with it...
//
// CVARS:
//
//   dod_shellshock "1" //Turn on(1)/off(0)
//
//   dod_shellshock_fade "1" //Turn on(1)/off(0) quick screen fade
//   dod_shellshock_fade_dmg "25" //Sets the minimum damage required
//
//   dod_shellshock_shake "1" //Turn on(1)/off(0) screen shake
//   dod_shellshock_shake_dmg "40" //Sets the minimum damage required
//
//   dod_shellshock_volume "1" //Turn on(1)/off(0) short volume loss
//   dod_shellshock_volume_dmg "40" //Sets the minimum damage required
//   dod_shellshock_volume_time1 "10" //How long you lose volume (10ths of a second)
//   dod_shellshock_volume_time2 "5" //Delay between each volume increase step (10ths of a second)
//   dod_shellshock_volume_inc 1  // Turn on(1)/off(0) increase of recover time
//   dod_shellshock_volume_inc_dmg 10  // How many damage that increase recover time
//   dod_shellshock_volume_inc_time 10  // Increased time (10ths of a second) 
//
//   dod_shellshock_ring "1" //Turn on(1)/off(0) ringing effect
//   dod_shellshock_ring_dmg "50" //Sets the minimum damage required
//
//   dod_shellshock_fov "0" //Turn on(1)/off(0) fov effect (unfinished)
//   dod_shellshock_fov_dmg "90" //Sets the minimum damage required
//
// Extra:
//
//      Put the "shellshock_ring3.mp3" in /dod/sound/misc/  
//
// Changelog:
//
//   - 05.01.2006 Version 0.1
//  	  Initial port of v3x's "he_damage_effect v0.2"
//  	  Added cvar to set min. dmg required
//	  Added Rockets as well as grenades
//
//   - 05.03.2006 Version 0.2
//  	  Added Garand & K43 buttstocks
//
//   - 05.05.2006 Version 0.3
//        Added CVAR for buttstocks
//	  Renamed to DoD Shell Shock
//
//   - 05.06.2006 Version 0.4
//        Removed buttstocks till I do it a better way
//        Changed from MSG_ONE to MSG_ONE_UNRELIABLE
//
//   - 05.10.2006 Version 0.5
//        Added CVARs for fade & shake (code from cadav0r)
//	  Added CVAR for volume
//
//   - 05.12.2006 Version 0.6
//        CVAR query bug fixed (thanks cadav0r)
//	  New method for volume effect (thanks cadav0r)
//	  Fixed volume staying at 0.0 bug
//
//   - 05.15.2006 Version 0.7
//	  Another fix for CVAR query problem
//        Added ringing sound MP3 (still plays during volume effect)
//	  Added CVAR for ringing effect
//	  Added FOV effect (defualts to 0 as im not satisfied with it yet)
//
//   - 05.18.2006 Version 0.7b
//	  Removed global damage cvar and added one for each effect
//
//   - 05.22.2006 Version 0.7c
//	  Fixed run-time error
//	  Adjusted a few random things...
//
//   - 05.24.2006 Version 0.7d
//	  Fixed 2 small errors becuase of my stupidity (thanks cadav0r)
//
//   - 06.09.2006 Version 0.8
//	  Added CVAR for how long you lose your volume
//	  Added CVAR for delay between each volume increase step (thanks cadav0r)
//	  New 'ringing' sound (thanks WARDOG)
//	  Adjusted ScreenFade & ScreenShake message variables
//
//////////////////////////////////////////////////////////////////////////////////

#include <amxmodx>
#include <engine>
#include <dodx>
#include <fun>

new gMsgScreenShake , gMsgScreenFade, gMsgSetFOV, p_dod_shellshock
new p_dod_shellshock_fade, p_dod_shellshock_shake, p_dod_shellshock_volume, p_dod_shellshock_volume_time1, p_dod_shellshock_volume_time2, p_dod_shellshock_ring, p_dod_shellshock_fov
//
new p_dod_shellshock_volume_inc, p_dod_shellshock_vol_inc_dmg, p_dod_shellshock_vol_inc_time
//
new p_dod_shellshock_fade_dmg, p_dod_shellshock_shake_dmg, p_dod_shellshock_volume_dmg, p_dod_shellshock_ring_dmg, p_dod_shellshock_fov_dmg

public plugin_init() {
  register_plugin("DoD Shell Shock" , "0.8" , "AMXX DoD Team & v3x")
  p_dod_shellshock = register_cvar("dod_shellshock", "1")
  //fade
  p_dod_shellshock_fade = register_cvar("dod_shellshock_fade", "1")
  p_dod_shellshock_fade_dmg = register_cvar("dod_shellshock_fade_dmg", "25")
  //shake 
  p_dod_shellshock_shake = register_cvar("dod_shellshock_shake", "1")
  p_dod_shellshock_shake_dmg = register_cvar("dod_shellshock_shake_dmg", "40")
  //volume
  p_dod_shellshock_volume = register_cvar("dod_shellshock_volume", "1")
  p_dod_shellshock_volume_dmg = register_cvar("dod_shellshock_volume_dmg", "50")
  p_dod_shellshock_volume_time1 = register_cvar("dod_shellshock_volume_time1", "10") //10ths of a second
  p_dod_shellshock_volume_time2 = register_cvar("dod_shellshock_volume_time2", "5") //10ths of a second

//
  p_dod_shellshock_volume_inc = register_cvar("dod_shellshock_volume_inc", "1")
  p_dod_shellshock_vol_inc_dmg = register_cvar("dod_shellshock_volume_inc_dmg", "10")
  p_dod_shellshock_vol_inc_time = register_cvar("dod_shellshock_volume_inc_time", "10") //10ths of a second
//
  //ring
  p_dod_shellshock_ring = register_cvar("dod_shellshock_ring", "1")
  p_dod_shellshock_ring_dmg = register_cvar("dod_shellshock_ring_dmg", "75")
  //fov
  p_dod_shellshock_fov = register_cvar("dod_shellshock_fov", "0")
  p_dod_shellshock_fov_dmg = register_cvar("dod_shellshock_fov_dmg", "99")  
    
  gMsgScreenShake = get_user_msgid("ScreenShake")
  gMsgScreenFade = get_user_msgid("ScreenFade")
  gMsgSetFOV = get_user_msgid("SetFOV")
  register_statsfwd(XMF_DAMAGE)
}

#define PA_LOW  30.0
#define PA_HIGH 60.0

new Float:gVolume[33], volumeup[33], gFov[33]

public plugin_precache() {

  precache_sound("misc/shellshock_ring_3.mp3")
}

public client_putinserver(id) {
  
  if (!is_user_bot(id) && is_user_connected(id) && get_pcvar_num(p_dod_shellshock) == 1 && get_pcvar_num(p_dod_shellshock_volume) == 1)
	{ 
	set_task(10.0, "cvar_query", id)
	}
}

public cvar_query(id) {		//added this func to fix cvar query bug

  if (!is_user_bot(id) && is_user_connected(id) && get_pcvar_num(p_dod_shellshock) == 1 && get_pcvar_num(p_dod_shellshock_volume) == 1)
	{
	query_client_cvar(id , "volume" , "cvar_result")
	}
}

public cvar_result(id, const cvar[] , const value[]) {
  
  if (!is_user_bot(id) && is_user_connected(id) && get_pcvar_num(p_dod_shellshock) == 1 && get_pcvar_num(p_dod_shellshock_volume) == 1)
	{
	if (gVolume[id] == 0)
		{
		gVolume[id] = 1.0
		}	
	gVolume[id] = str_to_float(value)
	}
}

public client_damage(attacker,victim,damage,wpnindex,hitplace,TA) {

  if(get_pcvar_num(p_dod_shellshock) != 1 || !is_user_connected(victim) || !is_user_alive(victim) || is_user_bot(victim))
	return PLUGIN_HANDLED

  if(wpnindex == DODW_MILLS_BOMB || wpnindex == DODW_HANDGRENADE || wpnindex == DODW_HANDGRENADE_EX || wpnindex == DODW_STICKGRENADE || wpnindex == DODW_STICKGRENADE_EX || wpnindex == DODW_PIAT || wpnindex == DODW_BAZOOKA || wpnindex == DODW_PANZERSCHRECK)
	{
	if(get_pcvar_num(p_dod_shellshock_ring) == 1 && damage >= get_pcvar_num(p_dod_shellshock_ring_dmg))
		{
		client_cmd(victim,"mp3 play sound/misc/shellshock_ring_3")
		}
    
	if(get_pcvar_num(p_dod_shellshock_volume) == 1 && damage >= get_pcvar_num(p_dod_shellshock_volume_dmg))
		{
		client_cmd(victim , "volume 0")
//
		volumeup[victim] = 0
	
		new noVolume;
		noVolume = get_pcvar_num(p_dod_shellshock_volume_time1)
		if (noVolume < 1)
			noVolume = 1

		if(get_pcvar_num(p_dod_shellshock_volume_inc) == 1)
			{
			new IncVolumeTime, Volumedmg, Incdmg, IncVolumedmg, inc;
			IncVolumeTime = get_pcvar_num(p_dod_shellshock_vol_inc_time)
			if (IncVolumeTime < 1)
				IncVolumeTime = 1

			Volumedmg = get_pcvar_num(p_dod_shellshock_volume_dmg)
			Incdmg = get_pcvar_num(p_dod_shellshock_vol_inc_dmg)
		
			// Initialization Start
			IncVolumedmg = Volumedmg
			inc = 0
			// Initialization End
			while((Volumedmg+(inc*IncVolumedmg)) < 100)
				{
				++inc
				IncVolumedmg = Volumedmg + (inc*Incdmg)
				if(damage > Volumedmg && damage <= IncVolumedmg) 
					noVolume = noVolume + (inc*IncVolumeTime)
				}
			}
		
		new Float:noVolumeTime, Float:ten, noVolume_str[5];
		num_to_str(noVolume, noVolume_str, 4)
		noVolumeTime = str_to_float(noVolume_str)
		ten = str_to_float("10")
		noVolumeTime = floatdiv(Float:noVolumeTime, Float:ten)
	
		set_task(noVolumeTime, "volume_up" , victim)
//
		}
	
	if(get_pcvar_num(p_dod_shellshock_shake) == 1 && damage >= get_pcvar_num(p_dod_shellshock_shake_dmg))
		{ 
	
		new Float:fVec[3];
		fVec[0] = random_float(PA_LOW , PA_HIGH)
		fVec[1] = random_float(PA_LOW , PA_HIGH)
		fVec[2] = random_float(PA_LOW , PA_HIGH)
		entity_set_vector(victim , EV_VEC_punchangle , fVec)
    
		message_begin(MSG_ONE_UNRELIABLE , gMsgScreenShake , {0,0,0} ,victim)
		write_short(1<<14) //ammount 
		write_short(1<<12) //lasts this long 
		write_short(2<<14) //frequency
		message_end()
		}
	
	if(get_pcvar_num(p_dod_shellshock_fade) == 1 && damage >= get_pcvar_num(p_dod_shellshock_fade_dmg))
		{
		message_begin(MSG_ONE_UNRELIABLE , gMsgScreenFade , {0,0,0} , victim)
		write_short(1<<13)  //duraiton  (old - 1<<11)
		write_short(1<<12)  //hold time  (old - 1<<10)
		write_short(0x0002)  //flags  (old - 1<<12)
		write_byte(225) //red
		write_byte(0) //green
		write_byte(0) //blue
		write_byte(160) //alpha
		message_end()
		}
	
	if(get_pcvar_num(p_dod_shellshock_fov) == 1 && damage >= get_pcvar_num(p_dod_shellshock_fov_dmg))
		{
		message_begin(MSG_ONE_UNRELIABLE, gMsgSetFOV, {0,0,0}, victim)
		write_byte(170)
		message_end() 
	
		gFov[victim] = 170
		set_task(0.5 , "reset_fov" , victim)
		}
	}
  return PLUGIN_HANDLED
}

public volume_up(id) {

  if(is_user_bot(id) || !is_user_connected(id))
	return PLUGIN_HANDLED
  
  new Float:set_value, valuestr[5], valuenum, Float:ten, Float: set_time
  valuenum = volumeup[id] + 1
  num_to_str(valuenum, valuestr, 4)
  set_value = str_to_float(valuestr)
  ten = str_to_float("10")
  set_value = floatdiv(Float:set_value, Float:ten)

  set_time = get_pcvar_float(p_dod_shellshock_volume_time2)
 
  if (set_time < 1.0)
	{
	set_time = 1.0
	}
	
  set_time = floatdiv(Float:set_time, Float:ten)
    
  if(set_value < gVolume[id]) 
	{
	client_cmd(id , "volume %f", set_value)
	++volumeup[id]
	set_task(set_time, "volume_up", id)
	} 
  else
	{
	client_cmd(id , "volume %f" , gVolume[id])
	volumeup[id] = 0
	}
  return PLUGIN_HANDLED
}

public reset_fov(id) {

  if (is_user_bot(id) || !is_user_connected(id))
	return PLUGIN_HANDLED
    
  gFov[id] = gFov[id] - 5

  if(gFov[id] > 90) 
	{	
	message_begin(MSG_ONE_UNRELIABLE, gMsgSetFOV, {0,0,0}, id)
	write_byte(gFov[id])
	message_end()
	
	set_task(0.2, "reset_fov", id)
	} 
  else
	{ 
	message_begin(MSG_ONE_UNRELIABLE, gMsgSetFOV, {0,0,0}, id)
	write_byte(90)
	message_end()
	}
  return PLUGIN_HANDLED
}