/***************************************************************************
 * plugin_ejl_timebomb.sma   version 4.0         Date: 10/26/2002
 *  Author: Eric Lidman      ejlmozart@hotmail.com
 *  Alias: Ludwig van        Upgrade: http://lidmanmusic.com/cs/plugins.html           
 *
 * Fixed: 10/26/02 Revised for adminmod 2.50.50
 * Fixed: 8/22/02  Minor tweaks including a timer correction scheme added
 * Added: 6/27/02  Command:  admin_timebombs_default
 * Added: 6/27/02  Option to use HLFX for firey explosions
 *
 * Modified by cactus to be more efficient at recognizing 'kamikazi'
 *
 * Modified by author to be sensitive to the friendlyfire cvar. This way if
 *  FF is off, you dont blow up your teamates. This plugin was designed for
 *  Counter-Strike. With the change to use the CS specific mp_friendlyfire
 *  cvar, I dont know if this will work with mods like TFC or others now.
 *  If it does, let me know. I already know that the C4 timer sound and
 *  part of the explosion sound will only be heard in CS.
 * 
 * Modified 3-30-02 by author to have a delay at round start for kamikazi
 *  runs. Also, within the first 10 seconds of roun start, the bomb will 
 *  only kill the bomber and no bystanders. LOGD is required to make these
 *  changes work. http://logd.sourceforge.net/
 *  Once you get LogD, find and change this one line in my script:
 *
 *   #define use_logd 1 // 0=no  1=yes
 *
 *  By default use_logd is set to 0 to make it comapatible for all users.
 *
 * You can have firey explosions if you have the HLFX dll installed 
 *  As of this version HLFX is only available for windows servers.
 *  Let us thank Lightfoot <lightfoot_sf@yahoo.ca> for coming up with the
 *  Windows HLFX dll. Will somebody please write the Linux version!! 
 *  You need to find this in the script and change it to 1
 *
 *   #define use_HLFX 1 // 0=no  1=yes
 *
 * By defaulf use_HLFX is set to 0 so that it is universally compatible.
 *  Note that whith the use of HLFX, the friendlyfire feature doesnt work
 *  because HLFX does its own blast radius calculation and takes its own
 *  killing action based on that redering the scripting here for
 *  friendlyfire sensitivity useless. Too bad. The LodD part of it
 *  (where you cant blow up others at spawn) still works though because
 *  I decided not to let HLFX do the killing in that event.
 *  Get latest HLFX here:    http://deadone.no-ip.org/dead_one/HLFX/
 *
 *
 * COMMANDS:
 * 
 *    say: kamikaze
 *    admin_timebombs < 0 | 1 >      
 *    admin_timebombs_default   
 *    admin_timebomb <target>
 *    admin_vote_timebomb <target>
 *
 *  Player can become a timebomb by saying "kamikazi" in chat. Admin can
 *  disable the kamikaze function with admin_timebombs 0 and turn it back
 *  on again with admin_timebombs 1. Admin can make any live player without
 *  immunity into a timebomb with admin_timebomb <target>. All players can
 *  start a vote to turn a player into a timebomb in much the same way that 
 *  admin_vote_map or admin_vote_kick works -- admin_vote_timebomb <target>.
 *  admin_timebombs_default sets the current timebombs mode as default by 
 *  writing it to the vault file and loading it at map start when plugins
 *  are initialized. Admin ACCESS_RCON is required to set default. 
 *  
 * 
 * THE DETAILS:
 *
 *    Timer has a 15 second fuse. Countdown is done with half-life sounds.
 *    Bystanders will also die when bomb explodes.
 *    You know you are a bystander (or bomb) if you hear the C4 timer beep.
 *    No more than one player can be a timebomb at any given time. 
 *    A timebomb player glows random colors during the countdown.
 *	Dead Players cannot become timebombs.
 *    There is a 5 minute delay between "kamikaze" runs for each player.
 *    A timebomb who dies before the end of countdown explodes one second
 *      after death, also killing bystanders.
 *
 * Make sure you have these in your adminmod.cfg:
 *  admin_fx 1
 *  allow_client_exec 1
 *  file_access_read 1
 *  file_access_write 1
 * Adminmod has them set to 0 by default, just change them to 1
 *
 * Additional credit: 
 *  	This plugin is a very, very, very loose spinoff on plugin_sank_dice,
 *    which I heavily modified, and then tore down to make this plugin.
 *    So thanks to Luke Sankey for the basic structure, or whats left of it.  
 *
 **************************************************************************/ 
 
#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
#include <sound>
 
/*
////////////////////////////////////////////////////////////////////////////
//
// Change these values below to whatever you want, but I did alot of testing
//  and I think they are actually best left alone.
//
////////////////////////////////////////////////////////////////////////////
*/
 
/* If you have the HLFX dll and want real firey explosions with your bomb */
#define use_HLFX 0 // 0=no  1=yes
 
/* If you have the metamod plugin LogD, this plugin takes advantage of it. */
#define use_logd 0 // 0=no  1=yes
 
/* How much time after round start the bomb must wait to kill bystanders */
#define ROUND_START_TIME 20
new round_start = 0;
 
/* Sets the bomb's kill radius (default 500)(key = playerheight is about 95)  */
new BOMBKILL_RANGE = 500;
 
/* Sets the timelimit between kamikaze runs for a player. (default 300 sec.) */
#define TIMEBOMBER_DELAY 300
 
/* Sets the vote ratio required to pass a timebomb vote (default 70 percent) */
#define TIMEBOMB_VOTE_RATIO 70
 
/* Who can call a timebomb vote  (default 1 = everyone) */
#define ACCESS_VOTE_TIMEBOMB 1
 
/* Admin access required to use admin_timebomb <target>   and admin_timebombs */
#define ACCESS_TIMEBOMB 128
 
/* TIMER fuse time (not intended to be set below 15) */
#define TIMEBOMBER_TIME 15
 
/* 
/////////////////////////////////////////////////////////////////////////////
//
// Dont bother editing blow this point unless you know what you are doing. 
// Its ok, however, change the messages between quotation marks if you want.
//
/////////////////////////////////////////////////////////////////////////////
*/
 
#define ACCESS_CONSOLE 131072
 
new STRING_VERSION[MAX_DATA_LENGTH] = "2.51";
 
new tb_timercheck = 0;
new bool:bIsBombing = false;
new LastBombTime[MAX_PLAYERS+1];
new bool:bBombsEnabled = true;
 
new LastBombedName[MAX_NAME_LENGTH];
new LastBomberIndex = 0;
new iTimebombed_Timer = 0;
 
new BlowemUpEarly = 0;
new BombRightGuy;
new BombGuyTeam;
 
public world_start(HLCommand,HLData,HLUserName,UserIndex){
   if(round_start == 1){
      return PLUGIN_HANDLED;
   }  
   new Params[MAX_DATA_LENGTH];
   convert_string(HLData,Params,MAX_DATA_LENGTH);
   if(Params[6]=='S') {
      round_start = 1;
      set_timer("roundstartover", ROUND_START_TIME, 0);
   }
   return PLUGIN_HANDLED;
}
 
public pre_world_start(HLCommand,HLData,HLUserName,UserIndex){
   round_start = 1;
   set_timer("roundstartover", ROUND_START_TIME, 0);
   return PLUGIN_HANDLED;
}
 
public roundstartover() {
   round_start = 0;
}
 
public plugin_init() 
{
	plugin_registerinfo("Human Time-Bomb Plugin", "say: kamakaze", STRING_VERSION);
	plugin_registercmd("admin_timebombs", "admin_timebombs", ACCESS_TIMEBOMB, "admin_timebombs <on|off>: Controls whether players can kamikaze.");	
	plugin_registercmd("admin_timebombs_default", "admin_tbomb_deflt", ACCESS_RCON, "admin_timebombs_default : Sets the current timebombs mode as the default via the vault file.");
	plugin_registercmd("admin_timebomb", "admin_timebomb", ACCESS_TIMEBOMB, "admin_timebomb <target>: Turns player into time-bomb.");
	plugin_registercmd("admin_vote_timebomb","admin_vote_timebomb",ACCESS_VOTE_TIMEBOMB,"admin_vote_timebomb <target>: Starts a vote to turn a target into a timebomb.");
	plugin_registercmd("say", "HandleSay", ACCESS_ALL);
#if use_logd==1
	plugin_registercmd("world_start", "world_start", ACCESS_CONSOLE);
	plugin_registercmd("pre_world_start", "pre_world_start", ACCESS_CONSOLE);
	exec( "logd_reg 61 admin_command pre_world_start" );
	exec( "logd_reg 62 admin_command world_start" );
#endif
 
	new VaultData;
	new timebomb_mode;	
	if(get_vaultnumdata("EJL_TBOMB_MODE", VaultData) != 0){
		timebomb_mode = VaultData;
	} else {
		timebomb_mode = 2;
		set_vaultnumdata("EJL_TBOMB_MODE", 2);
	}
	if(timebomb_mode == 1){
		bBombsEnabled = false;
	}	
	if(timebomb_mode == 2){
		bBombsEnabled = true;
	}
 
	return PLUGIN_CONTINUE;
}
 
public plugin_connect(HLUserName, HLIP, UserIndex)
{
	if (UserIndex >= 1 && UserIndex <= MAX_PLAYERS)
		LastBombTime[UserIndex] = 0;
 
	return PLUGIN_CONTINUE;
}
 
public plugin_disconnect(HLUserName, UserIndex) 
{
	if (UserIndex >= 1 && UserIndex <= MAX_PLAYERS)
		LastBombTime[UserIndex] = 0;
 
	return PLUGIN_CONTINUE;
}
 
public admin_timebombs(HLCommand, HLData, HLUserName, UserIndex) 
{
	new Data[MAX_DATA_LENGTH];
	new User[MAX_NAME_LENGTH];
	new Text[MAX_TEXT_LENGTH];
 
	new Red = random(256);
	new Green = random(256);
	new Blue = random(256);
 
	convert_string(HLData, Data, MAX_COMMAND_LENGTH);
	convert_string(HLUserName, User, MAX_NAME_LENGTH);
 
	if (check_param(Data) == 1)
	{
		bBombsEnabled = true;
		snprintf(Text, MAX_TEXT_LENGTH, "Ok, lets kamikaze!");
		centersay(Text, 5, Red, Green, Blue);
	}
	else 
	{
		bBombsEnabled = false;
		snprintf(Text, MAX_TEXT_LENGTH, "No more kamikazes.");
		centersay(Text, 5, Red, Green, Blue);
	}
 
	snprintf(Text, MAX_TEXT_LENGTH, "admin_timebombs %d", bBombsEnabled);
	selfmessage(Text);
 
	return PLUGIN_HANDLED;
}
 
public admin_tbomb_deflt(HLCommand, HLData, HLUserName, UserIndex){
 
	new Command[MAX_COMMAND_LENGTH];
	new User[MAX_NAME_LENGTH];
	new Data[MAX_DATA_LENGTH];
	convert_string(HLData,Data,MAX_DATA_LENGTH);
 	convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
	convert_string(HLUserName,User,MAX_NAME_LENGTH);
	log_command(User,Command,Data);
 
	if(bBombsEnabled == true){
		set_vaultnumdata("EJL_TBOMB_MODE", 2);
		selfmessage("The current timebomb mode, 'say kamikaze ALLOWED', has been set as the default.");
	}else{
		set_vaultnumdata("EJL_TBOMB_MODE", 1);
		selfmessage("The current timebomb mode, 'NO saying kamikaze', has been set as the default.");
	}
	return PLUGIN_HANDLED;
}
 
public admin_timebomb(HLCommand, HLData, HLUserName, UserIndex) 
{
	new Data[MAX_DATA_LENGTH];
	new User[MAX_NAME_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new TargetName[MAX_NAME_LENGTH];
	new Command[MAX_COMMAND_LENGTH];
	new BombGuy[MAX_DATA_LENGTH];
	new Name[MAX_NAME_LENGTH];
	new SessionID;
	new WONID;
	new AUTHID[MAX_AUTHID_LENGTH];
	new UserTeam, UserDead;
	new TargetIndex;
 
	new Red = random(256);
	new Green = random(256);
	new Blue = random(256);
 
	convert_string(HLData, Data, MAX_DATA_LENGTH);
	convert_string(HLUserName, User, MAX_NAME_LENGTH);
	convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
 
	if(systemtime() > tb_timercheck + (TIMEBOMBER_TIME + 40)){
		if(bIsBombing == true){
			kill_timer(iTimebombed_Timer);
			bIsBombing = false;
			log("[TIMEBOMB]   Timebomb timer killed. Bomb reset.");
		}
	}
 
	if (bIsBombing == true)
		{
			selfmessage("Someone else is a time-bomb now, please wait.");
			return PLUGIN_CONTINUE;
		}
	else{
		if (check_user(Data) == 1) {
		get_username(Data,TargetName,MAX_NAME_LENGTH);
		get_userindex(Data,TargetIndex);
		strcpy(BombGuy, TargetName, MAX_NAME_LENGTH);
		if (UserIndex != LastBomberIndex || streq(LastBombedName, TargetName) == 0) {
	  		say_command(User,Command,TargetName);
		}
		if(check_immunity(TargetName)!=0) {
			snprintf(Text, MAX_TEXT_LENGTH, "Laf. You can't turn %s into a time-bomb, you silly bear.", TargetName);
			messageex(User, Text, print_chat);
			return PLUGIN_CONTINUE;
		}
		if (playerinfo(TargetIndex, Name, MAX_NAME_LENGTH, SessionID, WONID, UserTeam, UserDead, AUTHID)){
			if (UserDead != 0){
				snprintf(Text, MAX_TEXT_LENGTH, "You can't turn %s into a time-bomb, he is already dead.", TargetName);
				messageex(User, Text, print_chat);
				return PLUGIN_CONTINUE;
			}
			else if (UserDead !=1){
				BombRightGuy = TargetIndex;
				BombGuyTeam = UserTeam;
				snprintf(Text, MAX_TEXT_LENGTH, "%s has turned %s into a human time-bomb.", User, TargetName);
				say(Text);
				snprintf(Text, MAX_TEXT_LENGTH, "%s will explode in 10 seconds", TargetName);
				typesay(Text, 1, Red, Green, Blue);
				glow(TargetName, Red, Green, Blue);	
				bIsBombing = true;
				tb_timercheck = systemtime();
				new i;
				new iMaxPlayers = maxplayercount();
				for (i = 1; i <= iMaxPlayers; i++) {
					if (playerinfo(i,Name,MAX_NAME_LENGTH,SessionID, WONID, UserTeam, UserDead, AUTHID) == 1) {
  						execclient(Name, "speak ^"warning _comma detonation device activated^"");
					}
				}
				iTimebombed_Timer = set_timer("Timebombed_Timer", 1, TIMEBOMBER_TIME, BombGuy);
				LastBomberIndex = UserIndex;
				} 
			else {
				selfmessage("Unrecognized player: ");
				selfmessage(Data);
			}
		}
		return PLUGIN_CONTINUE;	
	}
}
	return PLUGIN_CONTINUE;
}
 
public HandleSay(HLCommand, HLData, HLUserName, UserIndex) 
{
	new Data[MAX_DATA_LENGTH];
	new User[MAX_NAME_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new BombGuy[MAX_NAME_LENGTH];
 
	new Red = random(256);
	new Green = random(256);
	new Blue = random(256);
 
	convert_string(HLData, Data, MAX_DATA_LENGTH);
	convert_string(HLUserName, User, MAX_NAME_LENGTH);
 
	strcpy(BombGuy, User, MAX_DATA_LENGTH);
 
	strstripquotes(Data);
 
	Data[0] = Data[0] | 32;
 
	if (Data[0] != 'k') 
		return PLUGIN_CONTINUE;
 
	if ( ((strncasecmp(Data,"kamik",5) == 0) || (strncasecmp(Data,"kamak",5) == 0))){
		if (bBombsEnabled == false){
 			messageex(User, "<Server>  Admin has disabled the ability to 'kamikaze.'", print_chat);
			return PLUGIN_CONTINUE;
		}
		if(systemtime() > tb_timercheck + (TIMEBOMBER_TIME + 40)){
			if(bIsBombing == true){
				kill_timer(iTimebombed_Timer);
				bIsBombing = false;
				log("[TIMEBOMB]   Timebomb timer killed. Bomb reset.");
			}
		}
		new Name[MAX_NAME_LENGTH];
		new SessionID;
		new WONID;
		new AUTHID[MAX_AUTHID_LENGTH];
		new UserTeam, UserDead;
		if (playerinfo(UserIndex, Name, MAX_NAME_LENGTH, SessionID, WONID, UserTeam, UserDead, AUTHID)){
		if (UserDead != 0){
			messageex(User, "<Server>  You cant be a time-bomb, you are dead already.", print_chat);
			return PLUGIN_CONTINUE;
				}
		else if (UserDead !=1){
		new CurTime = systemtime();
		if (CurTime < (LastBombTime[UserIndex] + TIMEBOMBER_DELAY))
		{
			messageex(User, "<Server>  Sorry, there is a 5 minute delay between your bombings.", print_chat);
			return PLUGIN_CONTINUE;
		}
		else if (round_start == 1)
		{
			messageex(User, "<Server>  Sorry, it's too early in the round to become a time-bomb.", print_chat);
		}
		else if (bIsBombing == true)
		{
			messageex(User, "<Server>  Someone else is a time-bomb now, please wait.", print_chat);
			return PLUGIN_CONTINUE;
		}
		else
		{
			BombRightGuy = UserIndex;
			BombGuyTeam = UserTeam;
			snprintf(Text, MAX_TEXT_LENGTH, "<Server>  %s has become a human time-bomb. Everyone RUN for cover!", User);
			say(Text);
			snprintf(Text, MAX_TEXT_LENGTH, "%s will explode in %i seconds", User, TIMEBOMBER_TIME);
			typesay(Text, 1, Red, Green, Blue);
			glow(User, Red, Green, Blue);
			tb_timercheck = systemtime();	
			bIsBombing = true;
			new i;
			new iMaxPlayers = maxplayercount();
			for (i = 1; i <= iMaxPlayers; i++) {
				if (playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,UserTeam,UserDead,AUTHID) == 1) {
   					execclient(Name, "speak ^"warning _comma detonation device activated^"");
				}
			}
			iTimebombed_Timer = set_timer("Timebombed_Timer", 1, TIMEBOMBER_TIME, BombGuy);
			LastBombTime[UserIndex] = CurTime;
			}
		}
		return PLUGIN_CONTINUE;
	}
}
	return PLUGIN_CONTINUE;
}
 
public admin_vote_timebomb(HLCommand,HLData,HLUserName,UserIndex) {
	new Command[MAX_COMMAND_LENGTH];
	new Data[MAX_DATA_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new User[MAX_NAME_LENGTH];
	new AUTHID[MAX_AUTHID_LENGTH];
	new Name[MAX_NAME_LENGTH];
	new SessionID;
	new WONID; 
	new UserTeam, UserDead;
	new TargetIndex;
	new dummy[MAX_NUMBER_LENGTH];
 
	if(systemtime() > tb_timercheck + (TIMEBOMBER_TIME + 40)){
		if(bIsBombing == true){
			kill_timer(iTimebombed_Timer);
			bIsBombing = false;
			log("[TIMEBOMB]   Timebomb timer killed. Bomb reset.");
		}
	}
 
	if (vote_allowed()!=1) {
		selfmessage( "Vote not allowed at this time.");
		return PLUGIN_HANDLED;
	}
	if (bIsBombing == true){
		selfmessage("Someone else is a time-bomb now, please wait.");
		return PLUGIN_CONTINUE;
	}	
 
	convert_string(HLCommand,Command,MAX_COMMAND_LENGTH);
	convert_string(HLData,Data,MAX_DATA_LENGTH);
	convert_string(HLUserName,User,MAX_NAME_LENGTH);
 
	if (check_user(Data) == 1) {
		new real_user[MAX_NAME_LENGTH];
		get_username(Data,real_user,MAX_NAME_LENGTH);
		say_command(User,Command,Data);
		if(check_immunity(real_user)!=0) {
			snprintf(Text, MAX_TEXT_LENGTH, "Laf. You can't turn %s into a timebomb you silly bear.", real_user);
			say(Text);
		} else {
			get_userindex(Data,TargetIndex);
			if (playerinfo(TargetIndex, Name, MAX_NAME_LENGTH, SessionID, WONID, UserTeam, UserDead, AUTHID)){
				if (UserDead != 0){
					snprintf(Text, MAX_TEXT_LENGTH, "You can't turn %s into a time-bomb, he is already dead.", real_user);
					say(Text);
					return PLUGIN_CONTINUE;
				}
			}
			BombRightGuy = TargetIndex;
			tb_timercheck = systemtime();
			bIsBombing = true;
			snprintf(Text, MAX_TEXT_LENGTH, "Should we blow up %s?", real_user);
			set_vaultnumdata("EJL_VOTES_ONOFF", 1);
			vote(Text,"Yes","No","HandleBombVote",dummy);
		}
	} else {
		selfmessage("Unrecognized user name ");
		selfmessage(Data);
	}
	return PLUGIN_HANDLED;
}
 
/* Handle a timebomb vote's results. */
public HandleBombVote(WinningOption,HLUser,VoteCount,UserCount) {
	new strNumber[MAX_NUMBER_LENGTH];
	new Text[MAX_TEXT_LENGTH];
	new VoteUser[MAX_DATA_LENGTH];
	new BombGuy[MAX_DATA_LENGTH];
	new Name[MAX_NAME_LENGTH];
	new SessionID;
	new WONID;
	new AUTHID[MAX_AUTHID_LENGTH];
	new UserTeam, UserDead;
 
	new Red = random(256);
	new Green = random(256);
	new Blue = random(256);
 
	set_vaultnumdata("EJL_VOTES_ONOFF", 2);
 
	convert_string(HLUser,VoteUser,MAX_DATA_LENGTH);
	strcpy(BombGuy, VoteUser, MAX_NAME_LENGTH);
 
	if (WinningOption == 1) {
		new Ratio = TIMEBOMB_VOTE_RATIO;
		if (VoteCount >= Ratio*UserCount/100) {
 
			if (playerinfo(BombRightGuy, Name, MAX_NAME_LENGTH, SessionID, WONID, UserTeam, UserDead, AUTHID)){
				strcpy(VoteUser, Name, MAX_NAME_LENGTH);
				if (UserDead != 0){
					snprintf(Text, MAX_TEXT_LENGTH, "<Server> Can't turn %s into a time-bomb, he died already.", VoteUser);
					say(Text);
					bIsBombing = false;
					BlowemUpEarly = 0;
					BombRightGuy = 0;
					return PLUGIN_CONTINUE;
				}
				else if (UserDead !=1){
					snprintf(Text, MAX_TEXT_LENGTH, "%s will explode in %i seconds", VoteUser,TIMEBOMBER_TIME);
					typesay(Text, 1, Red, Green, Blue);
					glow(VoteUser, Red, Green, Blue);
					BombGuyTeam = UserTeam;	
					new i;
					new iMaxPlayers = maxplayercount();
					for (i = 1; i <= iMaxPlayers; i++) {
						if (playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,UserTeam,UserDead,AUTHID) == 1) {
  							execclient(Name, "speak ^"warning _comma detonation device activated^"");
						}
					}
					snprintf(Text, MAX_TEXT_LENGTH, "%s was turned into a timebomb due to a vote.", VoteUser);
					say(Text);
					message(Name,"You have been turned into a timebomb due to a vote.");
					iTimebombed_Timer = set_timer("Timebombed_Timer", 1, TIMEBOMBER_TIME, BombGuy);
					}
				} 
				else {
					selfmessage("Unrecognized player: ");
					selfmessage(VoteUser);
					}
			} else {
				numtostr(Ratio*UserCount/100,strNumber);
				bIsBombing = false;
				BlowemUpEarly = 0;
				BombRightGuy = 0;
				snprintf(Text, MAX_TEXT_LENGTH, "Bomb vote succeeded, but not enough votes for bomb (needed %s)",strNumber);
				say(Text);
			}
		} else {
		bIsBombing = false;
		BlowemUpEarly = 0;
		BombRightGuy = 0;
		say("Bomb vote failed.");
	}
	return PLUGIN_CONTINUE;
}
 
/***************************************************************************/
/*    Here is the Timer Function , the heart of the timebomb  */
 
public Timebombed_Timer(Timer, Repeat, HLUserName, BombGuy) 
{
	new Text[MAX_TEXT_LENGTH];
	new TargetBombName[MAX_NAME_LENGTH];
	new TargetBomb[MAX_NAME_LENGTH];
	new Countdown[MAX_TEXT_LENGTH];
	new i;
	new iMaxPlayers = maxplayercount();
	new Name[MAX_NAME_LENGTH];
	new COUNTSPEAK[MAX_TEXT_LENGTH];
	new C4_SOUND[MAX_TEXT_LENGTH];
	new C4_BEEP[MAX_TEXT_LENGTH];
 
	new Dead;
	new maxplayers = maxplayercount();
	new SessionID;
	new WONID;	
	new Team;
	new AUTHID[MAX_AUTHID_LENGTH];
	new x,y,z;
	new X,Y,Z;
 
	new Red = random(256);
	new Green = random(256);
	new Blue = random(256);
 
	convert_string(BombGuy,TargetBomb,MAX_NAME_LENGTH);
 
	if (BlowemUpEarly == 1){
		Repeat = 1;
	}
 
#if use_HLFX == 0
 
	if (Repeat-1 == 0){
		get_username(TargetBomb,TargetBombName,MAX_NAME_LENGTH);
		if (round_start == 0){	
			for (i=1; i<=maxplayers; i++){
				if( playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,Team,Dead,AUTHID)!=0){
					if(i == BombRightGuy)
						TargetBombName = Name;
					get_userorigin(TargetBomb, X, Y, Z);
					get_userorigin(Name,x,y,z);
					if( ! (X-x > BOMBKILL_RANGE || X-x < - BOMBKILL_RANGE || 
				   	Y-y > BOMBKILL_RANGE || Y-y < - BOMBKILL_RANGE ||
				   	Z-z > BOMBKILL_RANGE || Z-z < - BOMBKILL_RANGE) ){
						if(getvar("mp_friendlyfire")==0){
							if((Dead==0) && (Team != BombGuyTeam)){
								messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);			 
								slay(Name);
							}
						}
						if(getvar("mp_friendlyfire")==1){
							if(Dead==0){
								messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);			 
								slay(Name);
							}
						}							
					}
				}
			}
			if(getvar("mp_friendlyfire")==0){			
				slay(TargetBombName);
			}
		} else {
			slay(TargetBombName);
		}
		glow(TargetBomb, 0, 0, 0);
		playsoundall("weapons/c4_explode1.wav");
		playsoundall("weapons/awp1.wav");
		snprintf(Text, MAX_TEXT_LENGTH, "%s has exploded.", TargetBombName);
		typesay(Text, 1, Red, Green, Blue);
		bIsBombing = false;
		BlowemUpEarly = 0;
		BombRightGuy = 0;
		kill_timer(iTimebombed_Timer);
	}
 
#else
/*
   This is supposed to do the same as above but with using HLFX to kill instead of slay.
   The friendlyfire feature doesnt work because HLFX does its own blast radius calculation
   and takes its own killing action based on that redering the scripting here for
   friendlyfire sensitivity useless. Too bad. The LodD part of it (where you cant blow up 
   others at spawn) still works though because I decided not to let HLFX do the killing in
   that event. 
*/
	if (Repeat-1 == 0){
		// loop to get everyones location in a map and decide whether they are too close to the bomb
		// too close? well, kill em
		new Command[MAX_COMMAND_LENGTH];
		get_username(TargetBomb,TargetBombName,MAX_NAME_LENGTH);
		if (round_start == 0){
			for (i=1; i<=maxplayers; i++) {
				if( playerinfo(i,Name,MAX_NAME_LENGTH,SessionID,WONID,Team,Dead,AUTHID)!=0){
					// make sure we still have the right guy's name
					if(i == BombRightGuy){
						TargetBomb = Name;
					}
					// find everyone X is bomb, x is everyone else (one at a time)
					get_userorigin(TargetBomb, X, Y, Z);
					get_userorigin(Name,x,y,z);
					if( ! (X-x > BOMBKILL_RANGE || X-x < - BOMBKILL_RANGE || 
					   Y-y > BOMBKILL_RANGE || Y-y < - BOMBKILL_RANGE ||
					   Z-z > BOMBKILL_RANGE || Z-z < - BOMBKILL_RANGE) ){
						if(Dead==0) {							
							if( playerinfo(i, Name, MAX_NAME_LENGTH, SessionID, WONID, Team, Dead, AUTHID) != 0 )
							{
								if(i == BombRightGuy)
								{
									snprintf( Command, MAX_COMMAND_LENGTH, "fxExplode %d", SessionID);
									exec( Command );
									snprintf( Command, MAX_COMMAND_LENGTH, "fxShake %d", SessionID);
									exec( Command );
									messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);
								} else {
									if(getvar("mp_friendlyfire")==0){
										if(Team != BombGuyTeam){
											snprintf( Command, MAX_COMMAND_LENGTH, "fxExplodeSmall %d", SessionID);
											exec( Command );
											messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);
										}
									}else{
										snprintf( Command, MAX_COMMAND_LENGTH, "fxExplodeSmall %d", SessionID);
										exec( Command );
										messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);										
									}
								}
							}
						}
					}
				}
			}
		} else {
 
/*
  Disabled so that no explosions affecting bystanders happen at round start.
 
 
			if( playerinfo(BombRightGuy,Name,MAX_NAME_LENGTH,SessionID,WONID,Team,Dead,AUTHID)!=0){
				snprintf( Command, MAX_COMMAND_LENGTH, "fxExplode %d", SessionID);
				exec( Command );
				snprintf( Command, MAX_COMMAND_LENGTH, "fxShake %d", SessionID);
				exec( Command );
				messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);
			}
 
 
  We use slay instead below.
*/
 
			messageex(Name, "<Server>  Sorry, the bomb killed you.", print_chat);
			slay(TargetBombName);
		}
		glow(TargetBomb, 0, 0, 0);
		playsoundall("weapons/c4_explode1.wav");
		playsoundall("weapons/awp1.wav");
		snprintf(Text, MAX_TEXT_LENGTH, "%s has exploded.", TargetBombName);
		typesay(Text, 1, Red, Green, Blue);
		bIsBombing = false;
		BlowemUpEarly = 0;
		BombRightGuy = 0;
		kill_timer(iTimebombed_Timer);
	}
 
#endif
 
	else
	{
		if (Repeat >= 13){
			for (i = 1; i <= iMaxPlayers; i++) {
				if (playerinfo(i,Name,MAX_NAME_LENGTH, SessionID, WONID, Team, Dead, AUTHID) == 1) {
					if(i == BombRightGuy){
						TargetBomb = Name;
					}
					if (!strcmp(TargetBomb, Name)){
						if (Dead != 0){
							BlowemUpEarly = 1;
						}
					}
					get_userorigin(TargetBomb, X, Y, Z);
					get_userorigin(Name,x,y,z);
					if( ! (X-x > BOMBKILL_RANGE || X-x < - BOMBKILL_RANGE || 
					   Y-y > BOMBKILL_RANGE || Y-y < - BOMBKILL_RANGE ||
					   Z-z > BOMBKILL_RANGE || Z-z < - BOMBKILL_RANGE) ){
						playsound(Name, "weapons/c4_beep1.wav");
					}
				}
			}
			get_username(TargetBomb,TargetBombName,MAX_NAME_LENGTH);	
			glow(TargetBomb, Red, Green, Blue);
 			snprintf(Text, MAX_TEXT_LENGTH, "%s will explode in %d", TargetBombName, Repeat-1);
			typesay(Text, 1, Red, Green, Blue);
			return PLUGIN_CONTINUE;
		}
		if (Repeat == 12){
			strcpy(Countdown, "remaining", 20);
			strcpy(C4_BEEP, "weapons/c4_beep1.wav", 30);
		}
		if (Repeat == 11){
			strcpy(Countdown, "ten", 10);
			strcpy(C4_BEEP, "weapons/c4_beep1.wav", 30);
		}
		if (Repeat == 10){
			strcpy(Countdown, "nine", 10);
			strcpy(C4_BEEP, "weapons/c4_beep1.wav", 30);
		}
		if (Repeat == 9){
			strcpy(Countdown, "eight", 10);
			strcpy(C4_BEEP, "weapons/c4_beep1.wav", 30);
		}
		if (Repeat == 8){
			strcpy(Countdown, "seven", 10);
			strcpy(C4_BEEP, "weapons/c4_beep2.wav", 30);
		}
		if (Repeat == 7){
			strcpy(Countdown, "six", 10);
			strcpy(C4_BEEP, "weapons/c4_beep2.wav", 30);
		}
		if (Repeat == 6){
			strcpy(Countdown, "five", 10);
			strcpy(C4_BEEP, "weapons/c4_beep4.wav", 30);
		}
		if (Repeat == 5){
			strcpy(Countdown, "four", 10);
			strcpy(C4_BEEP, "weapons/c4_beep4.wav", 30);
		}
		if (Repeat == 4){
			strcpy(Countdown, "three", 10);
			strcpy(C4_BEEP, "weapons/c4_beep4.wav", 30);
		}
		if (Repeat == 3){
			strcpy(Countdown, "two", 10);
			strcpy(C4_BEEP, "weapons/c4_beep5.wav", 30);
		}
		if (Repeat == 2){
			strcpy(Countdown, "one", 10);
			strcpy(C4_BEEP, "weapons/c4_beep5.wav", 30);
		}
		if (Repeat == 1){
			return PLUGIN_CONTINUE;
		}
		snprintf(COUNTSPEAK, MAX_DATA_LENGTH, "speak ^"fvox/%s^"", Countdown);
		snprintf(C4_SOUND, MAX_DATA_LENGTH, "^"%s^"", C4_BEEP);
		for (i = 1; i <= iMaxPlayers; i++) {
			if (playerinfo(i,Name,MAX_NAME_LENGTH, SessionID, WONID, Team, Dead, AUTHID) == 1) {
				if(i == BombRightGuy){
					TargetBomb = Name;
				}
				if (!strcmp(TargetBomb, Name)){
					if (Dead != 0){						
						BlowemUpEarly = 1;
						}
					}
				get_userorigin(TargetBomb, X, Y, Z);
				get_userorigin(Name,x,y,z);
				if( ! (X-x > BOMBKILL_RANGE || X-x < - BOMBKILL_RANGE || 
				   Y-y > BOMBKILL_RANGE || Y-y < - BOMBKILL_RANGE ||
				   Z-z > BOMBKILL_RANGE || Z-z < - BOMBKILL_RANGE) ){
					playsound(Name, C4_SOUND);
				}
				execclient(Name, COUNTSPEAK);
			}
		}
		get_username(TargetBomb,TargetBombName,MAX_NAME_LENGTH);	
		glow(TargetBomb, Red, Green, Blue);
 		snprintf(Text, MAX_TEXT_LENGTH, "%s will explode in %d", TargetBombName, Repeat-1);
		typesay(Text, 1, Red, Green, Blue);
	}
	return PLUGIN_CONTINUE;
}