
/***************************************************************************
 * amx_ejl_timebomb.sma     release version 2.5a           Date: 11/17/02
 *  Author: Eric Lidman      ejlmozart@hotmail.com
 *  Alias: Ludwig van        Upgrade: http://lidmanmusic.com/cs/plugins.html           
 *
 * Formerly my Adminmod 'kamikazi' plugin re-written for AMX mod. 
 *
 * FX updated -- looks way cooler !!!
 *
 * COMMANDS:
 * 
 *    say: kamikaze
 *    amx_timebombs < 0 | 1 >      
 *    amx_timebombs_default
 *    amx_timebombs_lock
 *    amx_votetimebomb <part of nick>
 *    stopvote 
 *    amx_timebomb_credit < 0 | 1 >
 *    amx_timebomb_credit_default  
 *    amx_timebomb <part of nick>
 *
 *    Player can become a timebomb by saying "kamikazi" in chat. Admin can
 *    disable the kamikaze function with amx_timebombs 0 and turn it back
 *    on again with amx_timebombs 1. amx_timebombs_credit turns on and off
 *    the giving of frag credit to the kamikazi for any kills he makes by
 *    blowing up members of the other team. Admin can make any live player
 *    without immunity into a timebomb with amx_timebomb <part of nick>.
 *    amx_timebombs_default sets the current timebombs mode as default by 
 *    writing it to a vault file and loading it at map start when plugins
 *    are initialized. amx_timebomb_credit_default sets the current kamikazi
 *    frag credit mode as default just as admin_timebombs_default does.
 *    AMX ACCESS_RCON is required to set any defaults.
 *
 * THE DETAILS:
 *
 *    Timer has a 15 second fuse. Countdown is done with half-life sounds.
 *    Displayed countdown message is color coded by team (CS t=red ct=blue). 
 *    Bystanders will also die when bomb explodes. You know you are a 
 *    bystander (or bomb) if you hear the timer beep. No more than
 *    one player can kamikazi any given time. There is no limit to how many
 *    players can be bombs by an admin command. A timebomb player glows red
 *    during the countdown. Dead Players cannot become timebombs.
 *    There is a delay between "kamikaze" runs for each player to keep
 *    players from hogging the bomb. A timebomb player who dies before the
 *    end of countdown explodes one second after death, also killing
 *    bystanders. The bomb is sensitive to the friendlyfire cvar. This way
 *    if FF is off, you dont blow up your teamates. You earn a frag for each
 *    player of the opposing team you blow up as the bomber. This frag credit
 *    only appies as the admin allows and only for kamikazi runs. A player 
 *    who was turned into a timebomb by an admin recieves no credit.
 *    There is a delay at round start for kamikazi runs. Also, within the 
 *    first 10 seconds of round start, the bomb will only kill the bomber 
 *    and no bystanders even if FF is on. Kamikazis/timebombs do not carry 
 *    over into the next round and will be exploded at the end of the
 *    round (CS). New: bystanders, if far enough away may only get hurt by
 *    the bomb and not killed outright.
 *
 * New: Set kamikazi rule for particular maps and lock it if you wish.
 *    
 *    Create a file called kamikazi_config.txt and put it into your 
 *    ..addons/amx folder. The contents should be the name of the map 
 *    followed by 2 numbers which are 1 or 0. The first number turns on 
 *    and off kamikazi mode for a map, the second specifies whether the
 *    fist value is locked and cannot be changed by a lower admin.
 *    Example contents of a line:  de_dust 0 1
 *    That 0 turns kamikazi off for de_dust and the 1 locks that so admin
 *    cant change it. 
 *
 * Other Credits: 
 *      
 *    OLO -- for making AMXmod so that we can have a kamikaze with cool FX
 *    f117bomb -- for snippets admin_slay2 that helped me
 *    Ludwig van -- (lol -me) for for writing the original admimod version
 *
 * Excuses:
 *
 *    This is my first attempt at writing plugins for AMX. Dont laugh too
 *    hard at my code. Ill learn as I go.

ADD VOTE for KAMIKAZI ALLOW


 *
 **************************************************************************/
	
#include <amxmod>
#include <amxmisc>

/*    Feel free to modify these values if you wish    */


new BOMBKILL_RANGE = 450  // killing radius of bomb. (96 is playerheight)
new BOMBHURT_RANGE = 700  // hurt radius of bomb. (96 is playerheight)
new KAMIKAZI_DELAY = 40    // time between allowed kamikazi runs for a player
new BOMB_FUSE = 15        // fuse time


/*    End of things that are ok to edit       */

new votenumber = 0
new votecontroller[33][2]
new answer[128]
new option_name[4][32]
new option[4]
new Float:vote_ratio
new st_vote = 0
new totalvoters
new bool:bVoteToStop = false
new bool:bomb_lock = false
new bool:tfc_b = false

new vault_value[128]
new gmsgFade
new gmsgShake
new fuselight
new c4bomb
new gibs
new smoke 
new white 
new fire
new Float:ejl_nextbomb[33]
new Float:ejl_ff
new IsBomb[33]
new IsKamik[33]
new wasbomb[33]
new bool:bKamikAllow = true
new bool:bKamikCredit = true
new bool:rs = false


explode(vec1[3],id){ 
   // blast circles 
   message_begin( MSG_BROADCAST,SVC_TEMPENTITY,vec1) 
   write_byte( 21 ) 
   write_coord(vec1[0]) 
   write_coord(vec1[1]) 
   write_coord(vec1[2] + 16) 
   write_coord(vec1[0]) 
   write_coord(vec1[1]) 
   write_coord(vec1[2] + 1936) 
   write_short( white ) 
   write_byte( 0 ) // startframe 
   write_byte( 0 ) // framerate 
   write_byte( 3 ) // life 2
   write_byte( 20 ) // width 16 
   write_byte( 0 ) // noise 
   write_byte( 188 ) // r 
   write_byte( 220 ) // g 
   write_byte( 255 ) // b 
   write_byte( 255 ) //brightness 
   write_byte( 0 ) // speed 
   message_end() 
    
   //Explosion2 
   message_begin( MSG_BROADCAST,SVC_TEMPENTITY) 
   write_byte( 12 ) 
   write_coord(vec1[0]) 
   write_coord(vec1[1]) 
   write_coord(vec1[2])
   write_byte( 188 ) // byte (scale in 0.1's) 188 
   write_byte( 10 ) // byte (framerate) 
   message_end() 

   //TE_Explosion 
   message_begin( MSG_BROADCAST,SVC_TEMPENTITY,vec1) 
   write_byte( 3 ) 
   write_coord(vec1[0]) 
   write_coord(vec1[1]) 
   write_coord(vec1[2])
   write_short( fire ) 
   write_byte( 65 ) // byte (scale in 0.1's) 188 
   write_byte( 10 ) // byte (framerate) 
   write_byte( 0 ) // byte flags 
   message_end() 

   //TE_KILLPLAYERATTACHMENTS
   message_begin(MSG_BROADCAST,SVC_TEMPENTITY,{0,0,0},id)
   write_byte( 125 ) // will expire all TENTS attached to a player.
   write_byte( id ) // byte (entity index of player)
   message_end()

   //Smoke 
   message_begin( MSG_BROADCAST,SVC_TEMPENTITY,vec1) 
   write_byte( 5 ) // 5
   write_coord(vec1[0]) 
   write_coord(vec1[1]) 
   write_coord(vec1[2]) 
   write_short( smoke )
   write_byte( 20 )  // 2
   write_byte( 10 )  // 10
   message_end()

} 

public roundend_cleanup(){
	blowem_up(100)
	rs = true
	set_task(15.0,"roundstart_delay")
}

public roundstart_delay(){
	rs = false
}

public round_start(){
	new maxplayers = get_maxplayers()+1
	for (new a=1; a<maxplayers; a++){
		if(wasbomb[a] == 1){
			set_user_rendering(a,kRenderFxNone,255,255,255, kRenderNormal,16)
			wasbomb[a] = 0
		}
	}
	return PLUGIN_CONTINUE
}

public client_connect(id){
	ejl_nextbomb[id] = 0.0
	IsBomb[id] = 0
	IsKamik[id] = 0
	wasbomb[id] = 0
	votecontroller[id][1] = 0
	return PLUGIN_CONTINUE
}

public client_disconnect(id){
	ejl_nextbomb[id] = 0.0
	IsBomb[id] = 0
	IsKamik[id] = 0
	wasbomb[id] = 0
	votecontroller[id][1] = 0
	return PLUGIN_CONTINUE
}

public amx_timebombs(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if(bomb_lock == true){
		console_print(id,"[AMX] Kamikaze ON/OFF is locked. No change can be made unless you do amx_timebombs_lock")		
		return PLUGIN_HANDLED
	}
	if (read_argc() < 2){
		new onoff[4]
		if(bKamikAllow == true){
			copy(onoff, 4, "ON")
		}else{
			copy(onoff, 4, "OFF")
		}
		console_print(id,"[AMX] Usage: amx_timebombs < on | off >     Currently: %s", onoff)
		return PLUGIN_HANDLED
	}

	new arg[10]
	read_argv(1,arg,10)

	if ( (equal(arg,"on", 2)) || (equal(arg,"1", 1)) ){
		bKamikAllow = true
		console_print(id,"[AMX] Kamikaze mode is now ON")
		client_print(0,print_chat,"[AMX] Admin has turned Kamikaze mode ON")
	}else{
		bKamikAllow = false
		console_print(id,"[AMX] Kamikaze mode is now OFF")
		client_print(0,print_chat,"[AMX] Admin has turned Kamikaze mode OFF")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" timebombs_mode %s",
		name,get_user_userid(id),authid,arg)

	return PLUGIN_HANDLED
}

public amx_timebombs_d(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if(bKamikAllow == false){
		ejl_vault("WRITE","Timebombs","off")
		console_print(id,"[AMX] Kamikaze mode OFF   is now the default.")
	}else{
		ejl_vault("WRITE","Timebombs","on")
		console_print(id,"[AMX] Kamikaze mode ON    is now the default.")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" timebombs_mode_d",
		name,get_user_userid(id),authid)

	return PLUGIN_HANDLED
}

public amx_tb_credit(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if (read_argc() < 2){
		new onoff[4]
		if(bKamikCredit == true){
			copy(onoff, 4, "ON")
		}else{
			copy(onoff, 4, "OFF")
		}
		console_print(id,"[AMX] Usage: amx_timebomb_credit < on | off >     Currently: %s", onoff)
		return PLUGIN_HANDLED
	}

	new arg[10]
	read_argv(1,arg,10)

	if ( (equal(arg,"on", 2)) || (equal(arg,"1", 1)) ){
		bKamikCredit = true
		console_print(id,"[AMX] Kamikaze frag credit is now ON")
		client_print(0,print_chat,"[AMX] Admin has turned Kamikaze frag credit mode ON")
	}else{
		bKamikCredit = false
		console_print(id,"[AMX] Kamikaze frag credit is now OFF")
		client_print(0,print_chat,"[AMX] Admin has turned Kamikaze frag credit mode OFF")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" kamikazi_frag_cr %s",
		name,get_user_userid(id),authid,arg)

	return PLUGIN_HANDLED
}

public amx_tb_credit_d(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if(bKamikCredit == false){
		ejl_vault("WRITE","Kamikazi_FragCredit","off")
		console_print(id,"[AMX] Kamikaze frag credit:  OFF   is now the default.")
	}else{
		ejl_vault("WRITE","Kamikazi_FragCredit","on")
		console_print(id,"[AMX] Kamikaze frag credit:  ON    is now the default.")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" kamikazi_frag_cr_d",
		name,get_user_userid(id),authid)

	return PLUGIN_HANDLED
}

public amx_tfc_by(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if (read_argc() < 2){
		new onoff[4]
		if(tfc_b == true){
			copy(onoff, 4, "ON")
		}else{
			copy(onoff, 4, "OFF")
		}
		console_print(id,"[AMX] Usage: amx_timebomb_tfc_b < on | off >     Currently: %s", onoff)
		return PLUGIN_HANDLED
	}

	new arg[10]
	read_argv(1,arg,10)

	if ( (equal(arg,"on", 2)) || (equal(arg,"1", 1)) ){
		tfc_b = true
		console_print(id,"[AMX] TFC timebomb bystander damage ON")
		client_print(0,print_chat,"[AMX] Admin has turned TFC timebomb bystander damage ON")
	}else{
		tfc_b = false
		console_print(id,"[AMX] TFC timebomb bystander damage is now OFF")
		client_print(0,print_chat,"[AMX] Admin has turned TFC timebomb bystander damage OFF")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" tfc_bystander %s",
		name,get_user_userid(id),authid,arg)

	return PLUGIN_HANDLED
}

public amx_tfc_by_d(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if(tfc_b == false){
		ejl_vault("WRITE","TFC_Kamikazi_b","off")
		console_print(id,"[AMX] TFC timebomb bystander damage:  OFF   is now the default.")
	}else{
		ejl_vault("WRITE","TFC_Kamikazi_b","on")
		console_print(id,"[AMX] TFC timebomb bystander damage:  ON    is now the default.")
	}

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" tfc_bystander_d",
		name,get_user_userid(id),authid)

	return PLUGIN_HANDLED
}

public lock_unlock(id,level,cid){
	if (!cmd_access(id,level,cid,1))
		return PLUGIN_HANDLED

	if (bomb_lock == true){
		bomb_lock = false
		console_print(id,"[AMX] Kamikaze mode lock is OFF.")
	}else	{
		bomb_lock = true
		console_print(id,"[AMX] Kamikazi mode lock is ON.")
		if(bKamikAllow == true){
			console_print(id,"[AMX] You have locked kamikazi ON mode.")
		}else{
			console_print(id,"[AMX] You have locled Kamikazi OFF mode.")
		}
	}
	return PLUGIN_HANDLED
}

public check_votes()
{
	set_cvar_string("amx_vote_inprogress","0")
	ejl_vault("WRITE","CURRENT_VOTE","NULL")

	bVoteToStop = false
	for(new a = 0; a < 33; a++){
		votecontroller[a][1] = 0
	}
	if(st_vote == 1){
		st_vote = 0
		client_print(0,print_chat,"[AMX]  Voting sucessfully stopped.")
		return PLUGIN_HANDLED
	}

	new best = 0
	new best_count = 0
	for(new a = 0; a < 4; ++a) {
		if (option[a] > best_count){
			best_count = option[a]
			best = a
		}
	}
	new inum = totalvoters
	new Float:result_v = inum ? (float(option[best]) / float(inum)) : 0.0
	if (result_v >= vote_ratio) {
		new player = strtonum(option_name[0])
		new name2[32]
		get_user_name(player,name2,32)
		if(best == 0){
			if(is_user_alive(player) == 0){
				client_print(0,print_chat,"[AMX] %s is dead and cannot be turned into a bomb.",name2)
				return PLUGIN_HANDLED
			} 
			IsBomb[player] = BOMB_FUSE
			player_attachment(player)
			client_cmd(0,"spk ^"vox/warning _comma _comma detonation device activated^"")	
			client_print(0,print_chat,"[AMX] Voting successful. The result: %s has been turned into a timebomb by vote. (%d - %d of %d)",name2,option[0],option[1],totalvoters)
		}else{
			client_print(0,print_chat,"[AMX] Voting result: %s will not become a timebomb.  (%d - %d of %d)",name2,option[0],option[1],totalvoters)
			log_to_file("addons/amx/admin.log","World triggered ^"voting_success^" (needed ^"%.2f^") (ratio ^"%.2f^") (result ^"bomb^")",
				vote_ratio,result_v)
		}
	}else {
		client_print(0,print_chat,"[AMX] Bomb voting failed... Not enough for a clear majority  (%d - %d of %d)",option[0],option[1],totalvoters)
		log_to_file("addons/amx/admin.log","World triggered ^"voting_failure^" (needed ^"%.2f^") (ratio ^"%.2f^")",
			vote_ratio,result_v)
	}
	return PLUGIN_HANDLED
}

public vote_count(id,key){
	ejl_vault("READ","CURRENT_VOTE","")
	if(equal(vault_value,"TIMEBOMB")){
	new name[32]
	get_user_name(id,name,32)
	if(votenumber != votecontroller[id][0]){
		votecontroller[id][0] = votenumber
		if (get_cvar_float("amx_vote_answers")) {
			client_print(0,print_chat,"[AMX] %s voted for option # %d",name,key+1)
		}
		option[key] += 1
	}else{
		votecontroller[id][1] +=1
	}
	}else{
		return PLUGIN_CONTINUE
	}
	return PLUGIN_HANDLED
}

public admin_votebomb(id,level,cid){
	if (!cmd_access(id,level,cid,2))
		return PLUGIN_HANDLED

	new Float:voting = get_cvar_float("amx_last_voting")
	if (voting > get_gametime()){ 
		console_print(id,"There is already one voting...") 
		return PLUGIN_HANDLED 
	} 
	if (voting && voting + get_cvar_float("amx_vote_delay") > get_gametime()) { 
		console_print(id,"Voting not allowed at this time") 
		return PLUGIN_HANDLED 
	} 

	new inprogress[32]
	get_cvar_string("amx_vote_inprogress",inprogress,32)
	if(equal(inprogress, "0",1)){

	new arg[32]
	read_argv(1,arg,32)
	new player = cmd_target(id,arg,1)
	if (!player) return PLUGIN_HANDLED

	new menu_msg[256]
	new keys
	get_user_name(player,arg,32)
	if(is_user_alive(player) == 0){
		client_print(id,print_console,"[AMX] %s is dead and cannot be voted a bomb.",arg)
		return PLUGIN_HANDLED
	} 
	format(menu_msg,256,"\yShould we blow up %s?\w^n^n1.  Yes^n2.  No", arg)
	num_to_str(player,option_name[0],32)
	keys = (1<<0)|(1<<1)

	new authid[16],name[32]
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)
	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" vote bomb (target ^"%s^")",
		name,get_user_userid(id),authid,arg)

	new Float:vote_time = get_cvar_float("amx_vote_time") + 2.0 
	set_cvar_float("amx_last_voting",  get_gametime() + vote_time )

	vote_ratio = get_cvar_float("amx_votetimebomb_ratio")
	copy(answer,128, "bomb %s")
	for(new a = 0; a < 33; a++){
		votecontroller[a][1] = 0
	}
	votenumber++
	set_cvar_string("amx_vote_inprogress","1")
	ejl_vault("WRITE","CURRENT_VOTE","TIMEBOMB")	
	bVoteToStop = true

	totalvoters = 0
	new Team[33]
	new maxpl = get_maxplayers()+1
	for(new k = 1; k < maxpl; k++){
		get_user_team(k,Team,33)
		if(!((equali(Team,"UNAS",4)) || (equali(Team,"SPEC",4)) || (get_user_time(k)== 0) )){
			show_menu(k,keys,menu_msg,floatround(vote_time))
			totalvoters++
		}
	}

	set_task(vote_time,"check_votes")
	st_vote = 0	
	client_print(id,print_console,"[AMX] Voting has started...")
	for(new j = 0; j < 4;++j) option[j] = 0
	}else{
	client_print(id,print_console,"[AMX] Voting not allowed yet.")	
	}

	return PLUGIN_HANDLED
}

public stopvote(id){

	if (!(get_user_flags(id)&ADMIN_MAP)){
		client_print(id,print_console,"[AMX] You have no access to that command")
		return PLUGIN_HANDLED
	}
	if(bVoteToStop == true){
		new name[32]
		get_user_name(id,name,32)
		st_vote = 1
		client_print(id,print_console,"[AMX]  ADMIN !!! Ignore the unknown command message -- its ok")
		client_print(0,print_chat,"[AMX]  %s has disabled the vote in progress.",name)
	}
	return PLUGIN_CONTINUE
}

public admin_timebomb(id,level,cid){
	if (!cmd_access(id,level,cid,2))
		return PLUGIN_HANDLED

	new arg[32]
	read_argv(1,arg,32)
	new player = cmd_target(id,arg,1)
	if (!player) return PLUGIN_HANDLED
	if(is_user_alive(player) == 0){
		console_print(id,"[AMX] The player is dead and cannot be bombed")
		return PLUGIN_HANDLED
	}
	if(IsBomb[player] > 0){
		console_print(id,"[AMX] :  That player is already a bomb")
		return PLUGIN_HANDLED
	}
	IsBomb[player] = BOMB_FUSE
	new name2[32]
	get_user_name(player,name2,32)
	client_cmd(0,"spk ^"vox/warning _comma _comma detonation device activated^"")	
	client_print(0,print_chat,"[AMX] :  %s has become a human timebomb, run for cover!!!", name2)
	new authid[16],authid2[16],name[32]
	get_user_authid(player,authid2,16)
	get_user_authid(id,authid,16)
	get_user_name(id,name,32)

	player_attachment(player)

	log_to_file("addons/amx/admin.log","^"%s<%d><%s><>^" timebomb ^"%s<%d><%s><>^"",
		name,get_user_userid(id),authid, name2,get_user_userid(player),authid2 )

	console_print(id,"[AMX] Client ^"%s^" bombed",name2)
	client_print(0,print_chat,"[AMX] Admin:    %s  has bombed  %s",name,name2)
	return PLUGIN_HANDLED
}

public handle_say(id){
	new arg2[8]
	read_argv(1,arg2,8)
	new Float:gt = get_gametime()

	if ( (equal(arg2,"kamik",5)) || (equal(arg2,"kamak",5)) ){
		if(bKamikAllow == false){
			client_print(id,print_chat,"[AMX] :  Admin has disabled the ability to kamikaze.")
			return PLUGIN_HANDLED
		}
		if(is_user_alive(id) == 0){
			client_print(id,print_chat,"[AMX] :  You cannot become a bomb, you are already dead.")
			return PLUGIN_HANDLED
		}
		if(rs == true){
			client_print(id,print_chat,"[AMX] :  Its too early in the round to become a bomb.")
			return PLUGIN_HANDLED
		}
		if(IsBomb[id] > 0){
			client_print(id,print_chat,"[AMX] :  You are the bomb already.")
			return PLUGIN_HANDLED
		}
		new maxpl = get_maxplayers() +1
		for(new a = 1; a < maxpl; ++a) {
			if(IsKamik[a] == 1){
				client_print(id,print_chat,"[AMX] :  Wait your turn, someone else is the kamikazi.")
				return PLUGIN_HANDLED
			}
		}
		if(ejl_nextbomb[id] > gt ){
			client_print(id,print_chat,"[AMX] :  You were just a bomb a short while ago, give someone else a chance.")
			return PLUGIN_HANDLED
		}
		IsKamik[id] = 1
		IsBomb[id] = BOMB_FUSE
		ejl_nextbomb[id] = gt + KAMIKAZI_DELAY
		new name[32]
		get_user_name(id,name,32)
		player_attachment(id)
		client_cmd(0,"spk ^"vox/warning _comma _comma detonation device activated^"")	
		client_print(0,print_chat,"[AMX] :  %s has become a human timebomb, run for cover!!!", name)
		return PLUGIN_CONTINUE		
	}

	return PLUGIN_CONTINUE
}

public timebomb_timer(){

	new Float:gt = get_gametime()
	new hibomb = 100
	new maxpl = get_maxplayers() +1
	new a
	for(a = 1; a < maxpl; a++) {
		if ((IsBomb[a] != 0) && (IsBomb[a] < hibomb)){
			hibomb = a   		
		}
		if ( (IsKamik[a] == 1) && ((ejl_nextbomb[a] - KAMIKAZI_DELAY + BOMB_FUSE + 5) < gt) ){			
			IsKamik[a] = 0
			IsBomb[a] = 0
		}
	}

	for(a = 1; a < maxpl; a++) {
		if (IsBomb[a] > 0){
			emit_sound(a,CHAN_ITEM, "buttons/blip2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM)
			new origin[3]
			get_user_origin(a,origin)

			//TE_SPRITE
			message_begin(MSG_BROADCAST,SVC_TEMPENTITY,{0,0,0},a)
			write_byte(17) // additive sprite, plays 1 cycle
			write_coord(origin[0]) // pos
			write_coord(origin[1]) // pos
			write_coord(origin[2]+20) // pos
			write_short (fuselight) // spr index	
			write_byte(20) // (scale in 0.1's) 
			write_byte (200) //(brightness)
			message_end()

			if (IsBomb[a] == 1){
				blowem_up(a)   		
			}else{
				IsBomb[a] -= 1
				if (a == hibomb){ 
					new name[32]
					new team[32]
					get_user_name(a,name,32)
					get_user_team(a,team,32)
					if(equal(team,"T", 1)){
						set_hudmessage(200,0,0, 0.03, 0.76, 2, 0.02, 2.0, 0.01, 0.1, 2)
					}else{
						set_hudmessage(0,100,200, 0.03, 0.76, 2, 0.02, 2.0, 0.01, 0.1, 2)
					}
					show_hudmessage(0,"%s will explode in %d seconds.",name,IsBomb[a])
					if (IsBomb[a] == 11){
						client_cmd(0,"spk ^"fvox/remaining^"")
					}
					if (IsBomb[a] < 11){
						new temp[48]
						num_to_word(IsBomb[a],temp,48)
						client_cmd(0,"spk ^"fvox/%s^"",temp)
					}
				}
				if(is_user_alive(a) == 0){
					blowem_up(a)
				}
			}
		}
	}
}

public blowem_up(id){

	new bombguyfrags
	new lostkills
	new bgf_message = 0
	new players[32], inum
	new modname[32]
	get_modname(modname,31)
	if(id == 100){
		new maxpl = get_maxplayers() +1
		for(new a = 1; a < maxpl; a++) {
			if ((IsBomb[a] > 0) || (IsKamik[a] == 1)){
				IsKamik[a] = 0
				IsBomb[a] = 0
				new name[32]
				get_user_name(a,name,32)
				set_hudmessage(200,255,200, 0.03, 0.76, 2, 0.02, 2.0, 0.01, 0.1, 2)
				show_hudmessage(0,"%s has exploded.",name)
    				new origin[3]	
				get_user_origin(a,origin)
 				origin[2] = origin[2] - 26
				user_kill(a,1)
				explode(origin,a)
				wasbomb[a] = 1
			}
		}
	}else{
		if (IsBomb[id] > 0){
			new name[32]
			new team[32]
			new authid[40]
			new namev[32]
			new teamv[32]
			new authidv[40]
			new origin1[3]
			get_user_name(id,name,31)
			get_user_authid(id,authid,39)
			set_hudmessage(200,255,200, 0.03, 0.76, 2, 0.02, 2.0, 0.01, 0.1, 2)
			show_hudmessage(0,"%s has exploded.",name)
			ejl_ff = get_cvar_float("mp_friendlyfire")
    			new origin[3]	
 			get_user_origin(id,origin)
			get_user_team(id, team , 31)
			new maxpl = get_maxplayers() +1
			for(new a = 1; a < maxpl; a++) {
				if(is_user_alive(a) != 0){
 					get_user_origin(a,origin1)
					get_user_team(a,teamv,31)
					get_user_name(a,namev,31)
					get_user_authid(a,authidv,39) 
					if( ! (origin[0]-origin1[0] > BOMBKILL_RANGE || origin[0]-origin1[0] < - BOMBKILL_RANGE || 
				   	       origin[1]-origin1[1] > BOMBKILL_RANGE || origin[1]-origin1[1] < - BOMBKILL_RANGE ||
				   	       origin[2]-origin1[2] > BOMBKILL_RANGE || origin[2]-origin1[2] < - BOMBKILL_RANGE) ){
						if(ejl_ff == 0){
							if( (!equal(team, teamv)) || ( (equal(modname,"tfc")) && (tfc_b == true) ) ){
								client_print(a,print_chat,"[AMX] :  Sorry, the bomb killed you.")
								if((a != id) && (bKamikCredit == true) && (IsKamik[id] == 1) ){
									bombguyfrags = get_user_frags(id)
									bombguyfrags +=1
									bgf_message +=1
									set_user_frags(id,bombguyfrags)
									log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"Kamikaze Bomb^"",
										name,get_user_userid(id),authid,team,namev,get_user_userid(a),authidv,teamv)	
								}
								user_kill(a,1)
								explode(origin1,a)		 
							}
						}
						if(ejl_ff == 1){
							if(rs == false){
								client_print(a,print_chat,"[AMX] :  Sorry, the bomb killed you.")
								if((!equal(team, teamv)) && (bKamikCredit == true) && (IsKamik[id] == 1) ){
									bombguyfrags = get_user_frags(id)
									bombguyfrags +=1
									bgf_message +=1
									set_user_frags(id,bombguyfrags)
								}
								if((equal(team, teamv)) && (bKamikCredit == true) && (IsKamik[id] == 1) && (id != a) ){
									bombguyfrags = get_user_frags(id)
									bombguyfrags -=1
									bgf_message -=1
									lostkills +=1
									set_user_frags(id,bombguyfrags)
								}									
								if(a != id){
									explode(origin1,a)
									log_message("^"%s<%d><%s><%s>^" killed ^"%s<%d><%s><%s>^" with ^"Kamikaze Bomb^"",
										name,get_user_userid(id),authid,team,namev,get_user_userid(a),authidv,teamv)	
								}
								user_kill(a,1)
							}else{
								client_print(a,print_chat,"[AMX] :  Sorry, the bomb killed you.")
								if(a == id){
									user_kill(a,0)
									message_begin(MSG_ONE,gmsgFade,{0,0,0},id) 
									write_short( 1<<11 ) // fade lasts this long furation 
									write_short( 1<<11 ) // fade lasts this long hold time 
									write_short( 1<<12 ) // fade type (in / out) 
									write_byte( 250 ) // fade red 
									write_byte( 250 ) // fade green 
									write_byte( 250 ) // fade blue 
									write_byte( 255 ) // fade alpha 
									message_end()
								}
							}	 
						}							
					}
					else if( ! (origin[0]-origin1[0] > BOMBHURT_RANGE || origin[0]-origin1[0] < - BOMBHURT_RANGE || 
				   	       origin[1]-origin1[1] > BOMBHURT_RANGE || origin[1]-origin1[1] < - BOMBHURT_RANGE ||
				   	       origin[2]-origin1[2] > BOMBHURT_RANGE || origin[2]-origin1[2] < - BOMBHURT_RANGE) ){
						new health
						if(ejl_ff == 0){
							if( (!equal(team, teamv)) || ( (equal(modname,"tfc")) && (tfc_b == true) ) ){
								client_print(a,print_chat,"[AMX] :  Ouch, that bomb hurt you.")
								health = get_user_health(a)
								if(health > 50){
									set_user_health(a,health-50)
								}else{
									set_user_health(a,1)
								}
								if(get_cvar_num("mp_logdetail") == 3){
									log_message("^"%s<%d><%s><%s>^" attacked ^"%s<%d><%s><%s>^" with ^"Kamikaze Bomb^" (hit ^"chest^") (damage ^"50^") (health ^"%d^")",
										name,get_user_userid(id),authid,team,namev,get_user_userid(a),authidv,teamv,get_user_health(a))
								}
							}
						}
						if(ejl_ff == 1){
							if(rs == false){
								client_print(a,print_chat,"[AMX] :  Ouch, that bomb hurt you.")
								if(a != id){
									health = get_user_health(a)
									if(health > 50){
										set_user_health(a,health-50)
									}else{
										set_user_health(a,1)
									}
									if(get_cvar_num("mp_logdetail") == 3){
										log_message("^"%s<%d><%s><%s>^" attacked ^"%s<%d><%s><%s>^" with ^"Kamikaze Bomb^" (hit ^"chest^") (damage ^"50^") (health ^"%d^")",
											name,get_user_userid(id),authid,team,namev,get_user_userid(a),authidv,teamv,get_user_health(a))
									}
								}
							}
						}							
					}
				}
			}
			IsBomb[id] = 0
			IsKamik[id] = 0
			if(ejl_ff == 0){
				client_print(id,print_chat,"[AMX] :  Sorry, the bomb killed you.")
				user_kill(id,1)
				message_begin(MSG_ONE,gmsgFade,{0,0,0},id) 
				write_short( 1<<11 ) // fade lasts this long furation 
				write_short( 1<<11 ) // fade lasts this long hold time 
				write_short( 1<<12 ) // fade type (in / out) 
				write_byte( 250 ) // fade red 
				write_byte( 250 ) // fade green 
				write_byte( 250 ) // fade blue 
				write_byte( 255 ) // fade alpha 
				message_end()
			}
			if((bKamikCredit == true) && (bgf_message > 0)){
				if(ejl_ff == 0){
					client_print(id,print_chat,"[AMX] :  Your kamikazi attempt was a success:  You made %d KILLS.", bgf_message)
				}else{
					if(lostkills > 0){
						client_print(id,print_chat,"[AMX] :  Your kamikazi attempt was a success:  You made %d KILLS after %d TKs were subtracted.", bgf_message,lostkills)
					}else{
						client_print(id,print_chat,"[AMX] :  Your kamikazi attempt was a success:  You made %d KILLS.", bgf_message)
					}
				}
			}
 			origin[2] = origin[2] - 26  
			explode(origin,id)
			get_players(players,inum,"c")
			for(new i = 0 ;i < inum; ++i){
				message_begin(MSG_ONE,gmsgShake,{0,0,0},players[i]) 
				write_short( 1<<14 )// shake amount
				write_short( 1<<14 )// shake lasts this long
				write_short( 1<<14 )// shake noise frequency
				message_end()
			}

			//define TE_EXPLODEMODEL
			message_begin(MSG_BROADCAST,SVC_TEMPENTITY,{0,0,0},id)
			write_byte(107) // spherical shower of models, picks from set
			write_coord(origin[0]) // pos
			write_coord(origin[1]) 
			write_coord(origin[2]) 
			write_coord(175) //(velocity)
			write_short (gibs) //(model index)
			write_short (25) // (count)
			write_byte (100) // (life in 0.1's)		
			message_end()		
			wasbomb[id] = 1		
			set_user_rendering(id,kRenderFxNone, 0,0,0, kRenderTransAdd,0)
		}
	}
}

player_attachment(id){
	new att_life = (BOMB_FUSE * 10) + 20
	if(att_life > 255 || att_life < 1)
		att_life = 255

	//TE_PLAYERATTACHMENT
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY,{0,0,0},id)
	write_byte ( 124 ) //attaches a TENT to a player (this is a high-priority tent)
	write_byte ( id )  //(entity index of player) 
	write_coord ( 7 )  // ( attachment origin.z = player origin.z + vertical offset )
	write_short ( c4bomb ) // model index
	write_short ( att_life )     // (life * 10 )
	message_end()
}

public plugin_precache(){ 
	smoke = precache_model("sprites/steam1.spr") 
	white = precache_model("sprites/white.spr")
	fire = precache_model("sprites/explode1.spr")
	fuselight = precache_model("sprites/glow01.spr")
	c4bomb = precache_model("models/w_weaponbox.mdl")
	gibs = precache_model("models/hgibs.mdl")
	precache_sound( "buttons/blip2.wav")  
	return PLUGIN_CONTINUE 
}

public plugin_init(){
	register_plugin("Kamikaze","0.9","EJL")
	register_concmd("amx_timebombs","amx_timebombs",ADMIN_SLAY,"<on |off>   turns ability to kamikazi on and off")
	register_concmd("amx_timebombs_default","amx_timebombs_d",ADMIN_RCON,"sets the current kamikazi mode as default")
	register_concmd("amx_timebomb_credit","amx_tb_credit",ADMIN_SLAY,"<on |off>   turns kamikazi frag credit on and off")
	register_concmd("amx_timebomb_credit_default","amx_tb_credit_d",ADMIN_RCON,"sets the current kamikazi frag credit mode as default")
	register_concmd("amx_timebomb_tfc_b","amx_tfc_by",ADMIN_SLAY,"<on |off>   turns kamikazi tfc bystander damage on and off")
	register_concmd("amx_timebomb_tfc_b_default","amx_tfc_by_d",ADMIN_RCON,"sets the current kamikazi tfc bystader damage mode as default")
	register_concmd("amx_timebomb","admin_timebomb",ADMIN_SLAY,"< player >")
	register_concmd("amx_votetimebomb","admin_votebomb",ADMIN_USER,"< part of nick >")
	register_clcmd("stopvote","stopvote")
	register_clcmd("say","handle_say")
	register_event("SendAudio","roundend_cleanup","a","2=%!MRAD_terwin","2=%!MRAD_ctwin","2=%!MRAD_rounddraw")
	register_event("TextMsg","roundend_cleanup","a","2&#Game_C","2&#Game_w")
	register_event("SendAudio","round_start","bc","2=%!MRAD_GO","2=%!MRAD_MOVEOUT","2=%!MRAD_LETSGO","2=%!MRAD_LOCKNLOAD")	
	register_cvar("amx_luds_kamikaze","v2.5a",FCVAR_SERVER )

	register_concmd("amx_timebombs_lock","lock_unlock",ADMIN_RCON,"Locks/unlocks the current timebombs mode")
	register_cvar("amx_vote_inprogress","0")
	register_cvar("amx_last_voting","0")
	set_cvar_float("amx_last_voting",0.0)

	register_menucmd(register_menuid("Should we blow up ") ,(1<<0)|(1<<1)|(1<<2)|(1<<3),"vote_count")
	register_cvar("amx_votetimebomb_ratio","0.51")
	gmsgFade = get_user_msgid("ScreenFade")
	gmsgShake = get_user_msgid("ScreenShake")

	ejl_vault("READ","Timebombs","")
	if(equal(vault_value,"off"))
		bKamikAllow = false
	else
		bKamikAllow = true

	ejl_vault("READ","Kamikazi_FragCredit","")
	if(equal(vault_value,"off"))
		bKamikCredit = false
	else
		bKamikCredit = true

	ejl_vault("READ","TFC_Kamikazi_b","")
	if(equal(vault_value,"off"))
		tfc_b = false
	else
		tfc_b = true

	set_task(1.0,"timebomb_timer",765,"",0,"a", 9999)
	ejl_vault("WRITE","CURRENT_VOTE","NULL")
	set_task(2.2,"set_kamik_rule")

	return PLUGIN_CONTINUE
}

public set_kamik_rule(){ 
	new ThisMap[33]
	get_mapname(ThisMap, 33)
	if(file_exists("addons/amx/kamikazi_config.txt") == 1){
		new line = 0
		new data[128]
		new stextsize = 0
		new map[32]
		new value[2], value2[2]
		while((line=read_file("addons/amx/kamikazi_config.txt",line,data,128,stextsize))!=0){
			parse(data,map,32,value,2,value2,2)
			if(equali(map,ThisMap)){
				if(equal(value,"1",1)){
					bKamikAllow = true
				}else{
					bKamikAllow = false
				}
				if(equal(value2,"1",1)){
					bomb_lock = true
				}			
			}
		}
	}
	return PLUGIN_HANDLED
}

public ejl_vault(rw[],key[],value[]){
	new data[192]
	new stxtsize = 0
	new line = 0 
	new skip = 0
	new vkey[64]
	new vvalue[128]
	new vaultwrite[192]
	if(equal(rw,"READ")){
		if(file_exists("addons/amx/ejl_vault.ini") == 1){
			copy(vault_value,128,"")
			while((line=read_file("addons/amx/ejl_vault.ini",line,data,192,stxtsize))!=0){
				parse(data,vkey,64,vvalue,128)
				if(equal(vkey,key)){
					copy(vault_value,128,vvalue)
				}
			}
		}else{
			write_file("addons/amx/ejl_vault.ini", "**** Plugins use to store values -- immune to crashes and map changes ****", 0)
		}
	}
	else if(equal(rw,"WRITE")){
		if(file_exists("addons/amx/ejl_vault.ini") == 1){		
			format(vaultwrite,192,"%s %s",key,value)
			while((line=read_file("addons/amx/ejl_vault.ini",line,data,192,stxtsize))!=0){
				parse(data,vkey,64,vvalue,128)
				if(skip == 0){
					if( (equal(data,"")) || (equal(vkey,key)) ){
						skip = 1
						write_file("addons/amx/ejl_vault.ini",vaultwrite,line-1)
					}
				}
				else if(equal(vkey,key)){
					write_file("addons/amx/ejl_vault.ini","",line-1)
				}
			}
			if(skip == 0){
				write_file("addons/amx/ejl_vault.ini",vaultwrite,-1)
			}
		}
	}
	return PLUGIN_CONTINUE
}


