/*
* [EN] There is a tip for every1 : please, dont ask me about <warnings> ( compilation ). No errors, mod is working.
* I have just no time to finish it completely.
* [RU] Совет для всех : пожалуйста, не спрашивайте о предупреждениях ( при компиляции ). Нет ошибок. мод рабочий.
* Просто нету времени двоести до ума.
*/

#include <amxmodx>
#include <amxmisc>
#include <fakemeta_util>
#include <fun>
#include <engine>
#include <hamsandwich>
#include <nrs_main>
#include <nrs_const>
//#define WAR3FT_SUPPORT 1
//#define DEBUG 1
#if defined WAR3FT_SUPPORT
	#include <la2a>
#endif
#include <cstrike>
#include <dhudmessage>


//#define LA2A_SHOP	1
#if defined LA2A_SHOP
	#include <la2a_shop>
	#define DEF_COST	16000
	static TITLESHOP[60], itemname[100]
	new g_itemid, g_fast_respawn[33]
#endif

#define TITLE								"[NRS:S]"
#define MAX_ZOMBIE_ID							7
#define MAX_EVILCORP_ZOMBIE_ID						1
#define MAX_ZOMBIE_CREATED						10
#define maxdistance							550.0
#define HUNTER_STRIKE_XP						3500

#define SND_WIN 		"sound/npc_shared_sounds/win_game.mp3"
#define SND_EVOLUTION_1		"sound/npc_shared_sounds/zombi_evolution.mp3"
#define SND_EVOLUTION_2		"sound/npc_shared_sounds/zombi_evolution_female.mp3"
#define SND_PREPARE_4_BATTLE	"sound/npc_shared_sounds/after_wait.mp3"
#define SND_20_SEC_REMAIN	"sound/npc_shared_sounds/20secremain.mp3"

/*
* Credits 2 <iG_os> 4 Set_Buyzone plugin code
*/
new __MAPCONFIG_Ent, cvar_cycle_end
new NULL_MAP[100] = "no_change"


// Choose game-vote
const MAX_GAMES = 2
const WIN_GAME = 3000
new g_votes[MAX_GAMES], g_voted[33]


// Spawn-system
new const SPAWNS_FILE[] = "%s/nrs_configs/zc_%s.cfg"
const MAX_SPAWNS = 128
new Float:g_spawns[MAX_SPAWNS][4], g_spawns_r[MAX_SPAWNS][4], g_total_spawns, g_spawn_edit

// Spawn-creation system
new cache_spr_line//, Float:way_delay[33]
new const color_spawn_bot[3] = {255,255,255}
enum (+= 100)
{
	TASK_SHOW_SPAWNS = 2000,
	TASK_CREATE,
}
#define ID_SHOW_SPAWNS (taskid - TASK_SHOW_SPAWNS)


// Zombie-auto-spawn system
new g_ent_boss_alive, bool:BB_MODE, g_iEntBarrier, bool:HUNTER_BOSS_CREATED = false, bool:WAVE_HUNTER = false, bool:HUNTER_FINAL = false, HUNTER_SAVED_TIME, bool:HUNTER_award_given = false, bool:HUNTER_extra_wave = false, HUNTER_zombie_power = 0, g_last_minute = 0, NOW_MODE, bool:gVoting, bool:b_Mode = false, g_SyncHUD, fe

new g_Totally_Killed, g_counter = 0, bool:g_timerRunning = false


// Effects
new const g_arg[][] = { "bk", "dn", "ft", "lf", "rt", "up" } 


// fog settings
#define WAVE_BEFORE_BOSS	4
#define UPDATE_TIME		1.0
#define ENTITY_CLASS		"env_survival"
#define boss_entity_name 	"npc_cso_dione"//"npc_salma_zombie"
#define extra_entity_name	"npc_cso_juggernaut"
#define MAX_LOAD_MAPS		45
#define CONSTANT_FULL		10
#define TIME_2_START		60.0
#define CS_TEAM_SPEC		3
#define CS_TEAM_UNASSIGNED	0
new bool:g_gameended = false, Float:starttime, g_CONSTANT_SPAWNING = 0, MAPS_COUNT = 0, MAP_LOAD_NAME[MAX_LOAD_MAPS][125], __THIS_MAP_ID , ZOMBIE_2_SPAWN = -1, g_end_counter = 0
new g_death_time[33], cvar_respawn

new const lights_level[WAVE_BEFORE_BOSS+1][] = 
{
	"f",
	"e",
	"d",
	"c",
	"c"
}

// Player stuff
new g_kills[33]


public plugin_init() 
{
	register_plugin("NRS :: Survival Cooperative Mode","1.6","Good_Hash")
	register_concmd("nrs_surviralmenu", "menu_main")
	register_concmd("nrs_money", "give_money")
	register_dictionary("nrs_main.txt");
	register_dictionary("nrs_surviral.txt");
	
	cvar_cycle_end = register_cvar("nrs_cycle_end", NULL_MAP);
	
	#if defined LA2A_SHOP
		new itemabout[100]
		formatex(TITLESHOP, charsmax(TITLESHOP), "%L",0, "SHOP_TITLE" );
		formatex(itemname, 99, "%L", 0, "SHOP_FASTRESPAWN");
		formatex(itemabout, 99, "%L", 0, "SHOP_FASTRESPAWN_TIP");
		g_itemid = la2a_register_item(itemname, DEF_COST, itemabout, TEAM_ALL)
	#endif
	
	register_clcmd ( "chooseteam",				"LA2A_M_Menu" );
	RegisterHam( Ham_Killed, "player", "User_Respawn", 1);

	g_SyncHUD = CreateHudSyncObj( 1 );
	RegisterHam(Ham_TakeDamage, "player", "Block_Doing_Damage")
	
	new MapName[64], tFile[150], cfgdir[32], Len, i=0
	get_mapname(MapName, 63)
	get_configsdir(cfgdir, 63)
	format(tFile, charsmax(tFile), "%s/nrs_configs/surviral_mod_config.cfg", cfgdir)
	
	if(file_exists(tFile))
	{
		while(i < MAX_LOAD_MAPS && read_file(tFile, i , MAP_LOAD_NAME[MAPS_COUNT], 63, Len))
		{
			i++
			if(MAP_LOAD_NAME[MAPS_COUNT][0] == ';' || !Len)
			{
				continue
			}
			MAPS_COUNT++
		}
	}
	else
	{
		pause("a")
		log_amx("NRS Surviral : surviral_mod_config.cfg not found!")
	}
	
	
	for ( i = 0; i < MAPS_COUNT; i++ )
	{
		if ( equali(MapName, MAP_LOAD_NAME[i]) )
		{
			SURVIVAL_MODE_ON(i, MapName)
		}
	}
	
	if ( !WAVE_HUNTER )
	{
		pause("a")
	}
	
	set_cvar_string("amx_nextmap", get_my_next_map())
	set_task( 2.5, "checkTimeleft" );
}


public NRS_builder_off()
{
	set_cvar_num("nrs_builder", 0)
}


public SURVIVAL_MODE_ON(i, MapName[64])
{
	new Float:time_time = TIME_2_START
			
			
	if  (containi(MapName, "tls_" ) !=- 1)
	{
		BB_MODE = true
		g_iEntBarrier = find_ent_by_tname( -1, "gate" );
		set_cvar_num("nrs_builder", 1)
		time_time *= 3;
		set_task(time_time, "NRS_builder_off")
	}
	else
	{
		set_cvar_num("nrs_builder", 0)
		pause("ac", "nrs_builder.amxx")
	}
				
	starttime = get_gametime() + time_time;
	new cvar[32];
	formatex(cvar, 31, "%f", time_time);
	register_cvar("nrs_survival_starttime", cvar)
	cvar_respawn = register_cvar("nrs_survival_respawn", "1")
	
	
	WAVE_HUNTER = true
	new buyzone = create_entity("func_buyzone") // create buyzone entity and set it max size of map
	new Float:absmin[3] = {-89191.0, -89191.0, -89191.0}
	new Float:absmax[3] = {89191.0, 89191.0, 89191.0}
	DispatchSpawn(buyzone)
	entity_set_size(buyzone, absmin, absmax)
			
	__THIS_MAP_ID = i;
	__MAPCONFIG_Ent = create_entity("info_map_parameters")
	DispatchSpawn(__MAPCONFIG_Ent)
	DispatchKeyValue(__MAPCONFIG_Ent,"buying","0") // no limite team buy vaule
	DispatchKeyValue(__MAPCONFIG_Ent, "bombradius", "500")    // default bomb radius
	entity_set_int(__MAPCONFIG_Ent, EV_INT_iuser1, 1)
			
			
	/*new fog = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
	if(fog)
	{
		fm_set_kvd(fog, "density", "0.0055", "env_fog")
		fm_set_kvd(fog, "rendercolor", "244 184 116", "env_fog")
	}*/
	if ( !BB_MODE ) 
	{
		set_lights(lights_level[0])
		set_cvar_string("sv_skyname", "space")
	}
}


#if defined LA2A_SHOP
	public la2a_item_selected(id, itemid)
	{
		if(itemid != g_itemid)
			return PLUGIN_HANDLED
		
		if ( !g_fast_respawn[id]  )
		{
			g_fast_respawn[id] = true
		}
		else
		{
			cs_set_user_money_ul(id, cs_get_user_money_ul(id)+DEF_COST, 0)
			ChatColor(id, "%L",id, "SHOP_FASTRESPAWN_HAVE", TITLESHOP);
		}
		
		return PLUGIN_CONTINUE
	}
#endif


public LA2A_M_Menu ( id )
{
	Show_LA2users_Menu ( id )
	return PLUGIN_HANDLED;
}
	
public Show_LA2users_Menu(id)
{
	new menuTitle[127], main1[127]/*, main2[127], main3[127], main7[127], main8[127], main9[127]*/, NEXT[52], BACK[52], EXIT[52]
	
	formatex(NEXT, charsmax(NEXT), "%L", id, "NEXT");
	formatex(BACK, charsmax(BACK), "%L", id, "BACK");
	formatex(EXIT, charsmax(EXIT), "%L", id, "EXIT");
	
	formatex(menuTitle, charsmax(menuTitle), "%L", id, "MENU_MAIN_TITLE");
	
	formatex(main1, charsmax(main1), "%L", id, "MENU_MAIN_SHOPMENU3");

	
	new menu = menu_create(menuTitle, "__Show_LA2users_Menu");
	
	menu_additem(menu, main1, "1", 0);
	
	menu_setprop(menu, MPROP_NEXTNAME, NEXT)
	menu_setprop(menu, MPROP_BACKNAME, BACK)
	menu_setprop(menu, MPROP_EXITNAME, EXIT)
	menu_setprop(menu, MPROP_EXIT, MEXIT_ALL)

	
	menu_display(id, menu, 0); 
	
	return PLUGIN_HANDLED
}


public __Show_LA2users_Menu(id, menu, item) 
{ 
	if( item == MENU_EXIT) 
	{ 
		menu_destroy(menu); 
		return PLUGIN_HANDLED; 
	} 
	new data[6], iName[64]
	new access, callback; 
	menu_item_getinfo(menu, item, access, data,5, iName, 63, callback); 
	new key = str_to_num(data); 
	switch(key) 
	{
        
		case 1:
		{
			client_cmd(id, "say /shop")
			Show_LA2users_Menu(id)
		}
	}

	menu_destroy(menu)
	return PLUGIN_HANDLED
}

	
public give_money(id)
	if ( is_user_alive(id) && is_user_admin(id) )
	cs_set_user_money(id, 93000, 1)

public client_putinserver(id)
{
	new i, counter_c
	if ( starttime < get_gametime() )
	{
		for(i=1; i<32; i++)
		{
			if ( get_user_time(i) > 10 && is_user_connected(i) )
				counter_c++
		}
		if ( counter_c < 1 )
		{
			starttime = get_gametime()+TIME_2_START
			HUNTER_FINAL = false;
			HUNTER_BOSS_CREATED = false;
			HUNTER_zombie_power = 0
			
			
			if  (BB_MODE)
			{
				set_cvar_num("nrs_builder", 1)
				starttime = get_gametime()+TIME_2_START*3
				starttime = TIME_2_START*3;
				set_task(starttime, "NRS_builder_off")
			}
	
	
			update_lights()
			
			npc_reset()
		}
	}
}

public update_lights()
{
	if ( BB_MODE )
		return
	if ( !HUNTER_FINAL )
		set_lights(lights_level[HUNTER_zombie_power])
	else
		set_lights(lights_level[2])
}

public checkTimeleft( ) 
{
	register_think( ENTITY_CLASS, "fwdThink_Updater" );
	
	g_timerRunning = true;
	
	// initialize thinking entity...
	new iEntityTimer = create_entity( "info_target" );
	entity_set_string( iEntityTimer, EV_SZ_classname, ENTITY_CLASS );
	entity_set_float( iEntityTimer, EV_FL_nextthink, get_gametime() + UPDATE_TIME );
}

public fwdThink_Updater( iEntity ) 
{
	static iHours, iMinutes, iSeconds;
		
	iSeconds	= get_timeleft( );
	iMinutes	= iSeconds / 60;
	iHours		= iMinutes / 60;
	iSeconds	= iSeconds - iMinutes * 60;
	iMinutes	= iMinutes - iHours * 60;
		
		
	new i;
	
	//DEBUG!!!
	for ( i=1; i<33; i++ )
	{
		if ( is_user_alive(i) )
		{
			set_hudmessage(255, 255 , 255, -1.0, -0.05, 0, 0.01, 0.9, 0.3, 0.3 );
			show_hudmessage(i,  "%L",i, "HUD_PLAYER", get_user_health(i), g_kills[i]);
		}
		else if ( is_user_connected(i) )
		{
			Check_Respawn(i)
		}
		///
		#if defined DEBUG
		if ( is_user_connected(i) )
			if ( is_user_admin(i) )
				CREATOR_DEBUG_INFO(i)
		#endif
	}
	//DEBUG!!! REMOVE IT LATER!
	
	if ( starttime >= get_gametime() )
	{
		new seconds = floatround(starttime-get_gametime());
		g_last_minute = iMinutes
		
		set_dhudmessage(255, 255 , 255, 0.1,-0.7, 0, 0.01, 0.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_WAVE_LOBBY", seconds);
		
		new SND_2_PLAY[400]
		if ( seconds == 20 )
		{
			formatex(SND_2_PLAY, 399, "%s", SND_20_SEC_REMAIN)
		}
		else if (seconds == 3)
		{
			formatex(SND_2_PLAY, 399, "%s", SND_PREPARE_4_BATTLE)
		}
			
		if ( seconds == 20 || seconds == 3 )
			for ( i = 1; i < 33; i++ )
				if ( is_user_connected(i) )
					if ( get_user_team(i) > 0 )
						client_cmd(i, "mp3 play %s", SND_2_PLAY)
					
		entity_set_float( iEntity, EV_FL_nextthink, get_gametime() + UPDATE_TIME );
		return
	}
	
	SPAWN_ZOMBIES_CONSTANT()
		
	if ( HUNTER_zombie_power >= WAVE_BEFORE_BOSS || HUNTER_FINAL )
	{
		set_dhudmessage(255, 255 , 255, 0.2,-0.9, 0, 0.01, 0.9, 0.3, 0.3 );
			
		new hours = (time()-HUNTER_SAVED_TIME) / 3600
		new remainder = (time()-HUNTER_SAVED_TIME) % 3600
		new minutes = remainder / 60
		new seconds = remainder % 60
			
		new hrpre[5];
		new minpre[5]
		new secpre[5];
			
		if (hours < 10){
			formatex(hrpre, 4, "%s", "0");
		}else{
			formatex(hrpre, 4, "%s", "");
		}
			
		if (minutes < 10){
			formatex(minpre, 4, "%s", "0");
		}else{
			formatex(minpre, 4, "%s", "");
		}
			
		if (seconds < 10){
			formatex(secpre, 4, "%s", "0");
		}else{
			formatex(secpre, 4, "%s", "");
		}
			
		if ( !HUNTER_BOSS_CREATED )
			show_dhudmessage(0,  "%L",0, "STRIKE_WAVE_SURVIVE", hrpre, hours, minpre, minutes, secpre, seconds );
		else
			show_dhudmessage(0,  "%L",0, "STRIKE_BOSS_ANNOUNCER", g_end_counter );
				
		SPAWN_ZOMBIES_FINAL()
		if ( !HUNTER_FINAL ) 
		{
			HUNTER_FINAL = true
			npc_reset()
			set_task(1.0, "SPAWN_EXTRA")
		}
		if ( HUNTER_zombie_power == WAVE_BEFORE_BOSS-1 )
		{
			g_counter = HUNTER_zombie_power = 0
			update_lights()
		}
			
		if ( minutes == 3 && seconds == 0 )
		{
			//iMinutes = 5
			HUNTER_BOSS_CREATED = true
			g_ent_boss_alive = false
			npc_reset()
			set_dhudmessage(255, 255 , 255, 0.2,-0.7, 1, 0.01, 5.9, 0.3, 0.3 );
			show_dhudmessage(0,  "%L",0, "STRIKE_BOSS_WELCOME");
			task_exists(TASK_CREATE) ? 0 : set_task(5.0, "CREATE_BOSS", TASK_CREATE)
		}
	}
	else
	{
		set_dhudmessage(255, 255 , 255, 0.2,-0.9, 0, 0.01, 0.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_WAVE_COUNTER", HUNTER_zombie_power, iSeconds);
			
		if ( iMinutes != g_last_minute)
		{
			HUNTER_zombie_power++
			update_lights()
			//if ( HUNTER_zombie_power == 1 ) SPAWN_WITCH()
			
			ZOMBIE_2_SPAWN = -1
			
			new SND_2_PLAY[400]
			if ( GET_EVOLUTION() >= MAX_ZOMBIE_ID )
			{
				formatex(SND_2_PLAY, 399, "%s", SND_EVOLUTION_2)
			}
			else
			{
				formatex(SND_2_PLAY, 399, "%s", SND_EVOLUTION_1)
			}
			
			for ( i = 1; i < 33; i++ )
				if ( is_user_connected(i) )
					if ( get_user_team(i) > 0 )
						client_cmd(i, "mp3 play %s", SND_2_PLAY)
						
		}
		if ( ZOMBIE_2_SPAWN == -1 )
				ZOMBIE_2_SPAWN_CONFIG()
		else
		{
			SPAWN_ZOMBIES()
		}
				
		HUNTER_SAVED_TIME = time();
	}
		
	if ( g_last_minute == 5 )
	{
		npc_reset()
		set_dhudmessage(255, 255 , 255, 0.2,-0.9, 0, 12.01, 12.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_WAVE_WIN", g_Totally_Killed);
		if ( !HUNTER_award_given )
		{
			HUNTER_award_given = true
			static STRING[55]
			formatex(STRING, charsmax(STRING), "%L", 0, "XP_HUD")
			new i;
			for ( i = 1; i < 33; i++ )
				if ( is_user_connected(i) )
					if ( get_user_team(i) > 0 )
					{
						#if defined WAR3FT_SUPPORT
						give_user_xp(i, HUNTER_STRIKE_XP, false, true, STRING)
						#endif
						client_cmd(i, "mp3 play %s", SND_WIN)
					}
			set_task(15.0, "new_map")
		}
			
		return
	}
		
	if ( iMinutes == 18 && iSeconds == 30 && !HUNTER_extra_wave )
	{
		//SPAWN_ZOMBIES_N_WITCH()
		HUNTER_extra_wave = true
	}
	if ( !HUNTER_award_given )
		g_last_minute = iMinutes

	entity_set_float( iEntity, EV_FL_nextthink, get_gametime() + UPDATE_TIME );
	
	return;
}


public CREATE_BOSS()
{
	new Float:fOrigin[3], npc = create_npc(fOrigin, get_npc_classname_id(boss_entity_name))
	if ( !npc )
	{
		task_exists(TASK_CREATE) ? remove_task(TASK_CREATE) : 0
		set_task(5.0, "CREATE_BOSS", TASK_CREATE)
		return
	}
	else
	{
		g_ent_boss_alive = npc
		set_task(1.0, "Check_Boss", TASK_CREATE+npc)
	}
	
	
	if ( BB_MODE )
	{
		if ( pev_valid(g_iEntBarrier) )
		{
			set_pev(g_iEntBarrier,pev_solid,SOLID_NOT)
			set_pev(g_iEntBarrier,pev_renderamt,Float:{ 0.0 })
			set_pev(g_iEntBarrier, pev_effects, pev(g_iEntBarrier, pev_effects) | EF_NODRAW);
		}
	}
}

public Check_Boss(ent)
{
	if ( ent > TASK_CREATE )
		ent -= TASK_CREATE;
	if ( !pev_valid(ent) || !pev(ent, pev_health) )
		CREATE_BOSS()
}


public SPAWN_EXTRA()
{
	new Float:fOrigin[3]
	create_npc(fOrigin, get_npc_classname_id(extra_entity_name))
}

public event_gamestarted()
{
	event_npc_reset()
	if ( HUNTER_zombie_power > 0 )
	{
		HUNTER_zombie_power--
		update_lights()
	}
	
	/*if ( HUNTER_BOSS_CREATED )
	{
		set_dhudmessage(255, 255 , 255, 0.2,-0.7, 0, 0.01, 5.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_BOSS_WELCOME");
		set_task(5.0, "CREATE_BOSS", TASK_CREATE)
	}*/
}


public ZOMBIE_2_SPAWN_CONFIG()
{
	if (g_total_spawns && !HUNTER_BOSS_CREATED)
	{
		set_dhudmessage(255, 0 , 0, 0.1,-1.0, 0, 0.01, 6.0, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_WAVE_HUD");
		
		/*new MAX_ZOMBIE = get_playersnum()
		if ( MAX_ZOMBIE <= 3 )
		{
			//MAX_ZOMBIE = random_num(4,5)
			MAX_ZOMBIE = random_num(7, 11)
		}
		else if ( 7 >= MAX_ZOMBIE > 3 )
		{
			//MAX_ZOMBIE = random_num(10, 15)
			MAX_ZOMBIE = random_num(12, 20)
		}
		else
		{
			MAX_ZOMBIE = random_num(20+spawned_times,30+spawned_times)
		}*/
		new MAX_ZOMBIE = GET_DIFFICULTY()
		
		ZOMBIE_2_SPAWN = MAX_ZOMBIE;
	}
}

	
public SPAWN_ZOMBIES()
{
	if (g_total_spawns && ZOMBIE_2_SPAWN )
	{
		
		new random_zombie[50], point = random_num(0, g_total_spawns)
		static Float:POINT[3]
		POINT[0] = g_spawns[point][0]
		POINT[1] = g_spawns[point][1]
		POINT[2] = g_spawns[point][2]
		
		new ZM_ID = GET_EVOLUTION()
		new Zombie_Id
		
		for ( new i = 0; i < 5; i++ )
		{
			Zombie_Id = (random_num(1, ZM_ID))
			
			if (ZOMBIE_2_SPAWN) ZOMBIE_2_SPAWN--
			else return
			formatex(random_zombie, 49, "npc_cso_zm%i", Zombie_Id)
			random_zombie = EVOLUTION_FIX(Zombie_Id, random_zombie)
			if (create_npc(POINT, get_npc_classname_id(random_zombie))) g_counter++
		}
	}
}


public SPAWN_ZOMBIES_FINAL()
{
	if (g_total_spawns)
	{
		if ( g_counter >= 25 )
			return
			

		new random_zombie[50], point = random_num(0, g_total_spawns)
		static Float:POINT[3]
		POINT[0] = g_spawns[point][0]
		POINT[1] = g_spawns[point][1]
		POINT[2] = g_spawns[point][2]
		
		new ttl = GET_DIFFICULTY();
		new ZM_ID = GET_EVOLUTION()
		new Zombie_Id
		
		for (new i = 0; i < ttl; i++ )
		{
			Zombie_Id = (random_num(1, ZM_ID))
			//if (create_npc(POINT, get_npc_classname_id("npc_left4dead_zm")))g_counter++
			formatex(random_zombie, 49, "npc_cso_zm%i", Zombie_Id)
			random_zombie = EVOLUTION_FIX(Zombie_Id, random_zombie)
			if (create_npc(POINT, get_npc_classname_id(random_zombie)) ) g_counter++
		}
	}
}


public SPAWN_ZOMBIES_CONSTANT()
{
	if (g_total_spawns && !HUNTER_FINAL)
	{
		if ( g_CONSTANT_SPAWNING >= CONSTANT_FULL )
			return
		
		new random_zombie[50], point = random_num(0, g_total_spawns)
		static Float:POINT[3]
		POINT[0] = g_spawns[point][0]
		POINT[1] = g_spawns[point][1]
		POINT[2] = g_spawns[point][2]
		
		new Zombie_Id, ZM_ID = GET_EVOLUTION()
		
		Zombie_Id = (random_num(1, ZM_ID))
		formatex(random_zombie, 49, "npc_cso_zm%i", Zombie_Id)
		random_zombie = EVOLUTION_FIX(Zombie_Id, random_zombie)
		for(new i=0; i<random_num(1,3); i++)
			if ( create_npc(POINT, get_npc_classname_id(random_zombie)) ) g_CONSTANT_SPAWNING++
	}
}


stock GET_EVOLUTION_EVILCORP()
	return MAX_EVILCORP_ZOMBIE_ID

stock GET_DIFFICULTY()
{
	new zombies_num = get_playersnum()
	if ( zombies_num > 10 )
		zombies_num = random_num(18,23);
	else if ( 10 > zombies_num >= 6 )
		zombies_num = random_num(13,15);
	else if ( 6 > zombies_num >= 3 )
		zombies_num = random_num(10,12);
	else if ( 4>= zombies_num )
		zombies_num = random_num(9,10);
	else
		zombies_num = random_num(5,7);
	//if ( 10 > zombies_num >= 6 )
	//	zombies_num = random_num(9,10)
	///else
	//	zombies_num = random_num(5,7);
	//zombies_num = random_num(7,8)
	
	if ( HUNTER_FINAL ) zombies_num = floatround(zombies_num*random_float(0.2,0.3))
	else zombies_num = floatround(zombies_num*random_float(1.1,1.8))
	
	return zombies_num;
}

stock GET_EVOLUTION()
{
	/*if ( HUNTER_BOSS_CREATED || HUNTER_FINAL )
		return MAX_ZOMBIE_ID
	if ( HUNTER_zombie_power >= floatround(MAX_ZOMBIE_ID*0.6) )
		return MAX_ZOMBIE_ID
	if ( HUNTER_zombie_power >= floatround(MAX_ZOMBIE_ID*0.4) )
		return MAX_ZOMBIE_ID*/
	//return 4
	
	if ( HUNTER_BOSS_CREATED || HUNTER_FINAL )
		return MAX_ZOMBIE_ID
	else switch(random_num(0, HUNTER_zombie_power))
	{
		case 0: return random_num(1,4)
		case 1: return random_num(1,5)
		case 2: return random_num(1,6)
		case 3: return random_num(1,7)
		default:return random(MAX_ZOMBIE_ID)
	}
	return 4
}

stock EVOLUTION_FIX(zid, const zclass[50])
{
	new bool:every1 = false, szReturn[50]
	if ( HUNTER_BOSS_CREATED || HUNTER_FINAL )
		every1 = true;
		
	if ( HUNTER_zombie_power >= 1 || every1 ) 
		if ( zid == 4 ) 
		{ 
			if ( every1 ) if ( random_num(0,2) ) zid = 6; 
			formatex(szReturn, 49, "npc_cso_zm%i", zid); 
		}
		
	if ( HUNTER_zombie_power >= 2 || every1 ) 
		if ( zid == 1 ) 
		{  
			if ( every1 ) if ( random_num(0,1) ) formatex(szReturn, 49, "%s", "npc_cso_zm_pc"); 
		}
		
	if ( strlen(szReturn) ) return szReturn
	return zclass
}


public event_npc_damage(npc_id, attacker_id, Float:damage)
{
	if ( is_user_alive(attacker_id) )
		cs_set_user_money(attacker_id, cs_get_user_money(attacker_id) + floatround(1.6*damage) )		
}


public event_npc_init(ent)
{
	if ( !pev_valid(ent) )
		return;
	
	new Float:Health
	pev(ent, pev_health, Health)
	set_pev(ent, pev_health,  Health+50*HUNTER_zombie_power)
}



public event_npc_reset()
{
	/// Testing
	g_counter = 0
	g_CONSTANT_SPAWNING = 0
	ZOMBIE_2_SPAWN = -1
	
	if ( HUNTER_BOSS_CREATED && !g_gameended )
	{
		set_dhudmessage(255, 255 , 255, 0.2,-0.7, 0, 0.01, 5.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_BOSS_WELCOME");
		task_exists(TASK_CREATE) ? 0 : set_task(5.0, "CREATE_BOSS", TASK_CREATE)
	}
}


public event_npc_death(dead_ent, killer)
{
	if ( !pev_valid(dead_ent))
		return;
		
	g_Totally_Killed++
	
	if ( is_user_connected(killer) )
	{
		g_kills[killer]++
		ExecuteHamB( Ham_AddPoints, killer, 1, false );
	}
	
	
	if ( get_npc_classname_id(boss_entity_name) == get_npc_id(dead_ent) )
	{
		g_last_minute = 5
		g_gameended = true
	}
	
	if ( g_CONSTANT_SPAWNING )
		g_CONSTANT_SPAWNING--
	
	
	if ( g_counter ) g_counter--
	if ( HUNTER_BOSS_CREATED ) g_end_counter++
}


public plugin_precache()
{
	load_spawn_points();
	cache_spr_line = precache_model("sprites/laserbeam.spr")
	
	precache_generic(SND_WIN)
	precache_generic(SND_EVOLUTION_1)
	precache_generic(SND_EVOLUTION_2)
	precache_generic(SND_PREPARE_4_BATTLE)
	precache_generic(SND_20_SEC_REMAIN)
	
	new precache[64]
	for(new i; i < sizeof g_arg; i++)
	{ 
		formatex(precache, 63, "gfx/env/%s%s.tga", "space", g_arg[i]) 
		precache_generic(precache)
	} 
	
}


public Vote_Results()
{
	new temp[100], temp_num[5]
	gVoting = false
	
	if (g_votes[0] > g_votes[1])
	{
		//Start_Boss_Game()
		NOW_MODE = 0
	}
	else
	{
		NOW_MODE = 1
	}
	b_Mode = true
	
	
	formatex(temp_num, 4, "MODE_%i", NOW_MODE);
	formatex(temp, 99, "%L",0, TITLE);
	ChatColor(0, temp)
}

public Select_Boss_Game_starter()
	for ( new i = 1; i<33; i++ )
		if ( is_user_alive(i) )
			Select_Boss_Game(i)


public Select_Boss_Game(id)
{
	if (id>100)
		id -= 100
	if ( !is_user_alive(id) )
		return
		
	static temp_menu[64], menu_title[100];
	static menu
	
	formatex(menu_title, charsmax(menu_title), "%L",id, "MENU_MAIN_GAME_TYPE" );
	menu = menu_create(menu_title, "menu1_handle_admin")
	
	if ( g_voted[id] )
		formatex(temp_menu, 63, "%L",id, "MENU_GTYPE_WAVE_VOTED", g_votes[0] );
	else
		formatex(temp_menu, 63, "%L",id, "MENU_GTYPE_WAVE" );
	menu_additem(menu, temp_menu, "0")
	
	if ( g_voted[id] )
		formatex(temp_menu, 63, "%L",id, "MENU_GTYPE_SURVIRAL_VOTED", g_votes[1] );
	else
		formatex(temp_menu, 63, "%L",id, "MENU_GTYPE_SURVIRAL" );
	menu_additem(menu, temp_menu, "1")
	
	if ( g_voted[id] )
	{
		menu_setprop(menu, MPROP_EXIT, MEXIT_NEVER)
		if ( gVoting )
			set_task(1.0, "Select_Boss_Game", id+100)
	}
	else
		menu_setprop(menu, MPROP_EXIT, MEXIT_ALL)
	menu_display(id, menu, 0)	
	
	return

}

public client_disconnect(id)
{
	if ( g_voted[id] )
	{
		g_votes[g_voted[id]]--
		g_voted[id] = 0
	}
}


public menu1_handle_admin(id, menu, item)
{
	if(item == MENU_EXIT)
	{
		menu_destroy(menu)
		return PLUGIN_HANDLED
	}
	
	static data[6], szName[64], access, callback
	static temp_integer1
	menu_item_getinfo(menu, item, access, data, charsmax(data), szName, charsmax(szName), callback)
	
	temp_integer1 = str_to_num(data)
	g_votes[temp_integer1]++
	g_voted[id] = temp_integer1
	Select_Boss_Game(id)
		
	return PLUGIN_CONTINUE
}


public new_map()
{
	new nextmap[122]
	
	if ( __THIS_MAP_ID+1 >= MAPS_COUNT )
	{
		new endMap[100]
		get_pcvar_string(cvar_cycle_end, endMap, 99)
		if ( !equal(endMap, NULL_MAP) )
			formatex(nextmap, 121, "%s", endMap )
		else
			formatex(nextmap, 121, "%s", MAP_LOAD_NAME[0] )
	}
	else
	{
		formatex(nextmap, 121, "%s", MAP_LOAD_NAME[__THIS_MAP_ID+1] )
	}

	server_cmd("changelevel %s", nextmap)
}


get_my_next_map()
{
	new nextmap[122]
	if ( __THIS_MAP_ID+1 >= MAPS_COUNT )
	{
		formatex(nextmap, 121, "%s", MAP_LOAD_NAME[0] )
	}
	else
	{
		formatex(nextmap, 121, "%s", MAP_LOAD_NAME[__THIS_MAP_ID+1] )
	}
	return nextmap
}


load_spawn_points()
{
	// Check for spawns points of the current map
	new cfgdir[32], mapname[32], filepath[100], linedata[64]
	get_configsdir(cfgdir, charsmax(cfgdir))
	get_mapname(mapname, charsmax(mapname))
	formatex(filepath, charsmax(filepath), SPAWNS_FILE, cfgdir, mapname)
	
	// Load spawns points
	if (file_exists(filepath))
	{
		new file = fopen(filepath,"rt"), row[4][6]/*, gate*/
		
		while (file && !feof(file))
		{
			fgets(file, linedata, charsmax(linedata))
			
			// invalid spawn
			if(!linedata[0] || str_count(linedata,' ') < 2) continue;
			
			// get spawn point data
			parse(linedata,row[0],5,row[1],5,row[2],5,row[3],5)
			
			/* origin
			gate = str_to_num(row[0])
			if (gate == 1 && g_total_spawns_gates1<MAX_SPAWNS)
			{
				g_spawns_gates_1[g_total_spawns_gates1][0] = floatstr(row[1])
				g_spawns_gates_1[g_total_spawns_gates1][1] = floatstr(row[2])
				g_spawns_gates_1[g_total_spawns_gates1][2] = floatstr(row[3])
				g_total_spawns_gates1++
			}
			else if (gate == 2 && g_total_spawns_gates2<MAX_SPAWNS)
			{
				g_spawns_gates_2[g_total_spawns_gates2][0] = floatstr(row[1])
				g_spawns_gates_2[g_total_spawns_gates2][1] = floatstr(row[2])
				g_spawns_gates_2[g_total_spawns_gates2][2] = floatstr(row[3])
				g_total_spawns_gates2++
			}
			else */
			if (g_total_spawns<MAX_SPAWNS)
			{
				g_spawns[g_total_spawns][0] = str_to_float(row[1])
				g_spawns[g_total_spawns][1] = str_to_float(row[2])
				g_spawns[g_total_spawns][2] = str_to_float(row[3])
				/*new ent = create_entity("info_target")
				if ( !fe ) fe = ent
				dllfunc(DLLFunc_Spawn, ent)
				entity_set_int(ent, EV_INT_solid, SOLID_NOT)
				entity_set_int(ent, EV_INT_movetype, MOVETYPE_NONE)
				entity_set_float(ent, EV_FL_takedamage, 0.0)
				entity_set_float(ent, EV_FL_nextthink, halflife_time() + 0.1)
				set_pev(ent, pev_origin, g_spawns[g_total_spawns])//(ent, g_spawns[g_total_spawns])
				
				drop_to_floor(ent)
				
				//log_amx("CREATING : ent origin is %i %i %i", floatround(g_spawns[g_total_spawns][0]), floatround(g_spawns[g_total_spawns][1]), floatround(g_spawns[g_total_spawns][2]))
	
				if (!g_hamnpc)
				{
					g_entThink = RegisterHamFromEntity(Ham_Think, ent, "fw_think")
					g_hamnpc = 1
				}
				else
				{
					if ( g_disabled_Ent_Forwards )
					{
						EnableHamForward( g_entThink ) 
						g_disabled_Ent_Forwards = false;
					}
				}*/
				g_total_spawns++
			}
		}
		if (file) fclose(file)
	}
	//if ( !g_total_spawns )
	///	pause("ad")
}
stock str_count(const str[], searchchar)
{
	new count, i, len = strlen(str)
	
	for (i = 0; i <= len; i++)
	{
		if(str[i] == searchchar)
			count++
	}
	
	return count;
}



public Block_Doing_Damage(victim, inflictor, attacker, Float:damage, damagetype)
{
	if ( !b_Mode && !WAVE_HUNTER)
		return HAM_IGNORED
	
	if(damagetype & DMG_GENERIC || victim == attacker || !is_user_alive(victim) || !is_user_connected(attacker))
		return HAM_IGNORED
	
	if ( is_user_connected(victim) && is_user_connected(attacker) )
		return HAM_SUPERCEDE
		
	return HAM_IGNORED
}



public fw_think(ent)
{
	if ( !pev_valid(ent) )
		return HAM_IGNORED;
			
	new i, Float:Dist, Float:myOrigin[3], Float:plOrigin[3], random_zombie[50]
	entity_set_float(ent, EV_FL_nextthink, halflife_time() + 0.8)
	pev(ent, pev_origin, myOrigin)
	
	for ( i = 1; i < 33; i++ )
	{
		if ( !is_user_alive(i) )
			return HAM_IGNORED

		if ( !fm_is_ent_visible(i, ent ) )
			return HAM_IGNORED
			
		pev(i, pev_origin, plOrigin)
		Dist = get_distance_f(myOrigin, plOrigin)
		
		if(Dist > maxdistance)
			return HAM_IGNORED
			
		set_hudmessage(0, 0, 255, -1.0, -1.0)
		if ( fe == ent ) show_hudmessage(0, "Surviral : Dist = %i", floatround(Dist))
		
		new znum = count_nearly_zombies(/*ent, */myOrigin)
		if ( znum <= 5 && MAX_ZOMBIE_CREATED >= znum)
		{
			//if ( random_num(0,1) )
			//{
				formatex(random_zombie, 49, "npc_cso_zm%i", random_num(1,MAX_ZOMBIE_ID))
				create_npc(myOrigin, get_npc_classname_id(random_zombie))
			//}
		}
		
		//if ( fe == ent ) log_amx("ent THINK origin is %i %i %i", floatround(myOrigin[0]), floatround(myOrigin[1]), floatround(myOrigin[2]))
	}

	return HAM_HANDLED
}

stock count_nearly_zombies(/*ent, */Float:ent_origin[3])
{
	new o, counter, Float:entOrigin[3];
	for ( o = 1; o < 516; o++ )
	{
		if ( !pev_valid(o))
			continue
			
		//if ( !is_visible(o, ent ) )
		//	continue
			
		pev(o, pev_origin, entOrigin)
		
		if ( get_distance_f(ent_origin, entOrigin) < 600.0 )
			counter++
	}
	return counter
}
/*
public client_PreThink(id)
{
	if ( is_user_alive(id) )
	{
		if ( way_delay[id] <= get_gametime() )
		{
			new Float:vel[3];
			get_user_velocity(id, vel)
			if ( vector_length(vel ) > 180.0 )
			{
				way_delay[id] = get_gametime() + random_float(0.5, 2.0)
				Check_NPC_Spawner(id)				
			}
		}
	}
}

public Check_NPC_Spawner(id)
{
	static i, Float:Dist, Float:Origin[3], Float: ent_origin[3], Float:VicOrigin[3], random_zombie[50];
	for ( i=0; i<g_total_spawns; i++ )
	{
		if (!pev_valid(i) ) continue
		if ( !fm_is_ent_visible(i, id) )
		
		
		pev(id, pev_origin, Origin)
		pev(i, pev_origin, VicOrigin)
		Dist = get_distance_f(Origin, VicOrigin)
		if(Dist <= maxdistance)
		{
			ent_origin[0] = g_spawns[i][0]
			ent_origin[1] = g_spawns[i][1]
			ent_origin[2] = g_spawns[i][2]
			formatex(random_zombie, 49, "npc_cso_zm%i", random_num(1,MAX_ZOMBIE_ID))
			create_npc(ent_origin, get_npc_classname_id(random_zombie))
			
			set_hudmessage(0, 0, 255, -1.0, -1.0)
			show_hudmessage(id, "Surviral : created %s!", random_zombie)
			
		}
	}
}
*/

//######################################################################
// MENU MAIN
//######################################################################
public menu_main(id)
{
	// check is admin
	//if (!is_user_admin(id)) return PLUGIN_HANDLED;
	
	// remove task
	if (task_exists(id+TASK_SHOW_SPAWNS)) remove_task(id+TASK_SHOW_SPAWNS)
	
	// create main menu
	new title[64], item_name[3][64]
	format(title, charsmax(title), "%L:", LANG_PLAYER, "MENU_MAIN_TITLE")
	format(item_name[0], 63, "%L", LANG_PLAYER, "MENU_MAIN_ITEM_SPAWNS")

	new mHandleID = menu_create(title, "menu_main_handler")
	menu_additem(mHandleID, item_name[0], "spawn", 0)
	menu_display(id, mHandleID, 0)	

	return PLUGIN_HANDLED;
}

public menu_main_handler(id, menu, item)
{
	if (item == MENU_EXIT)
	{
		menu_destroy(menu)
		return;
	}
	
	new itemid[32], itemname[32], access
	menu_item_getinfo(menu, item, access, itemid, charsmax(itemid), itemname, charsmax(itemname), access)

	if (equal(itemid, "spawn"))
	{
		// set task show point
		if (task_exists(id+TASK_SHOW_SPAWNS)) remove_task(id+TASK_SHOW_SPAWNS)
		set_task(1.0, "task_show_spawns", id+TASK_SHOW_SPAWNS, _, _, "b")
	
		spawn_main(id)
	}
	
	menu_destroy(menu)
}


public spawn_main(id)
{
	// remove spawns choose
	g_spawn_edit = -1
	
	// create menu
	new title[64], item_name[5][64]
	format(title, charsmax(title), "%L", LANG_PLAYER, "MENU_SPAWNS_TITLE", g_total_spawns, MAX_SPAWNS)
	format(item_name[0], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ITEM_ADD")
	format(item_name[1], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ITEM_EDIT")
	format(item_name[2], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ITEM_SAVE")
	format(item_name[3], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ITEM_LOAD")
	format(item_name[4], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ITEM_DEL")

	new mHandleID = menu_create(title, "spawn_main_handler")
	menu_additem(mHandleID, item_name[0], "add", 0)
	menu_additem(mHandleID, item_name[1], "edit", 0)
	menu_additem(mHandleID, item_name[2], "save", 0)
	menu_additem(mHandleID, item_name[3], "load", 0)
	menu_additem(mHandleID, item_name[4], "del", 0)
	menu_display(id, mHandleID, 0)
}
public spawn_main_handler(id, menu, item)
{
	if (item == MENU_EXIT)
	{
		// destroy menu
		menu_destroy(menu)
		// show menu main
		menu_main(id)
		return;
	}
	
	new itemid[32], itemname[32], access
	menu_item_getinfo(menu, item, access, itemid, charsmax(itemid), itemname, charsmax(itemname), access)
	menu_destroy(menu)
	
	if (equal(itemid, "add"))
	{
		spawn_create(id)
		return;
	}
	else if (equal(itemid, "edit"))
	{
		// set first value for g_spawn_edit
		g_spawn_edit = 0
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_CREATING_NOW"\
		, TITLE)
		color_saytext(id, message)
		return;
		
		//spawn_edit(id)
		
		//return;
	}
	else if (equal(itemid, "save")) spawn_save()
	else if (equal(itemid, "load")) spawn_load()
	else if (equal(itemid, "del")) spawn_del(1)
	
	// show main menu
	spawn_main(id)
}

// ===================== spawn create =====================
public spawn_create(id)
{
	// remove spawns choose
	g_spawn_edit = -1
	
	// create menu
	new title[64], item_name[3][64]
	format(title, charsmax(title), "[NST Points] %L", LANG_PLAYER, "MENU_SPAWNS_ADD_TITLE", g_total_spawns, MAX_SPAWNS)
	format(item_name[0], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ADD_ITEM_ADD")
	format(item_name[1], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ADD_ITEM_ADD_BOSS")
	format(item_name[2], 63, "%L", LANG_PLAYER, "MENU_SPAWNS_ADD_ITEM_DEL")

	new mHandleID = menu_create(title, "spawn_create_handler")
	menu_additem(mHandleID, item_name[0], "add", 0)
	menu_additem(mHandleID, item_name[1], "add_boss", 0)
	menu_additem(mHandleID, item_name[2], "del", 0)
	menu_display(id, mHandleID, 0)
}
public spawn_create_handler(id, menu, item)
{
	if (item == MENU_EXIT)
	{
		// destroy menu
		menu_destroy(menu)
		// show menu main
		spawn_main(id)
		return;
	}
	
	new itemid[32], itemname[32], access
	menu_item_getinfo(menu, item, access, itemid, charsmax(itemid), itemname, charsmax(itemname), access)
	menu_destroy(menu)

	if (equali(itemid, "add")) spawn_create_add(id)
	else if (equali(itemid, "add_boss")) spawn_create_add(id, 1)
	else if (equali(itemid, "del")) spawn_del()

	// return menu create spawns
	spawn_create(id)
	
	return;
}
spawn_create_add(id, boss=0)
{
	// check max points
	if (g_total_spawns>=MAX_SPAWNS)
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_MAX_SPAWNS", TITLE, MAX_SPAWNS)
		color_saytext(id, message)
		return;
	}
	
	// add current points
	new Float:originF[3]/*, origin[3]*/
	pev(id, pev_origin, originF)
	/*origin[0] = floatround(originF[0])
	origin[1] = floatround(originF[1])
	origin[2] = floatround(originF[2])*/
	
	if (!is_point(originF) || !spawn_check_dist(originF))
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_SPAWNS_DIST", TITLE)
		color_saytext(id, message)
		return;
	}
	
	g_spawns[g_total_spawns][0] = originF[0]
	g_spawns[g_total_spawns][1] = originF[1]
	g_spawns[g_total_spawns][2] = originF[2]
	g_spawns[g_total_spawns][3] = float(boss)
	g_total_spawns ++
}


// ===================== spawn save =====================
spawn_save()
{
	// check total
	if (!g_total_spawns)
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_SPAWNS_NOTVALUE", TITLE)
		color_saytext(0, message)
		return;
	}

	// get url file
	new cfgdir[142], mapname[142], urlfile[154]
	get_configsdir(cfgdir, charsmax(cfgdir))
	get_mapname(mapname, charsmax(mapname))
	formatex(urlfile, charsmax(urlfile), SPAWNS_FILE, cfgdir, mapname)

	// save file
	if (file_exists(urlfile)) delete_file(urlfile)
	new lineset[128]
	for (new i=0; i<g_total_spawns; i++)
	{
		if (!g_spawns[i][0] && !g_spawns[i][1] && !g_spawns[i][2]) break;
		
		format(lineset, charsmax(lineset), "%i %i %i %i", floatround(g_spawns[i][3]), floatround(g_spawns[i][0]), floatround(g_spawns[i][1]), floatround(g_spawns[i][2]))
		write_file(urlfile, lineset, i)
	}
	
	// show notice
	new message[128]
	format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_SAVESPAWN_COMPLETE", TITLE)
	color_saytext(0, message)
}

// ===================== spawn load =====================
spawn_load()
{
	// Check for spawns points of the current map
	new cfgdir[32], mapname[32], filepath[100], linedata[64], Float:point[3]
	get_configsdir(cfgdir, charsmax(cfgdir))
	get_mapname(mapname, charsmax(mapname))
	formatex(filepath, charsmax(filepath), SPAWNS_FILE, cfgdir, mapname)
	
	// check file exit
	if (!file_exists(filepath))
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_FILE_EXIT", TITLE, filepath)
		color_saytext(0, message)
		return;
	}
	
	// first reset value
	reset_spawn()
	
	// Load spawns points
	new file = fopen(filepath,"rt"), row[4][6]
	while (file && !feof(file))
	{
		fgets(file, linedata, charsmax(linedata))
		
		// invalid spawn
		if(!linedata[0] || str_count(linedata,' ') < 2) continue;
		
		// get spawn point data
		parse(linedata,row[0],5,row[1],5,row[2],5,row[3],5)
		
		// set spawnst
		point[0] = str_to_float(row[1])
		point[1] = str_to_float(row[2])
		point[2] = str_to_float(row[3])
		if (is_point(point))
		{
			g_spawns[g_total_spawns][0] = point[0]
			g_spawns[g_total_spawns][1] = point[1]
			g_spawns[g_total_spawns][2] = point[2]
			g_spawns[g_total_spawns][3] = str_to_float(row[0])
	
			// increase spawn count
			g_total_spawns ++
			if (g_total_spawns>=MAX_SPAWNS) break;
		}
	}
	if (file) fclose(file)
	
	// notice
	if (g_total_spawns)
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_LOADSPAWN_COMPLETE", TITLE, g_total_spawns)
		color_saytext(0, message)
	}
}

public task_show_spawns(taskid)
{
	new id = ID_SHOW_SPAWNS
	spawn_show(id)
}

spawn_show(id)
{
	if (!g_total_spawns) return;
	
	new color[3], Float:start[3], Float:end[3]
	for (new i=0; i<g_total_spawns; i++)
	{
		/*if (i==g_spawn_edit) color = color_point_edit
		else if (g_spawns[i][3]) color = color_spawn_boss
		else */
		color = color_spawn_bot
		start[0] = g_spawns[i][0]
		start[1] = g_spawns[i][1]
		start[2] = g_spawns[i][2]
		if (!is_point(start)) return;
		end = start
		start[2] -= 36
		end[2] += 36

		create_line_point(id, start, end, color)
	}
}
spawn_del(all=0)
{
	// check total
	if (!g_total_spawns)
	{
		new message[128]
		format(message, charsmax(message), ">x04%s >x01%L", LANG_PLAYER, "NOTICE_SPAWNS_NOTVALUE", TITLE)
		color_saytext(0, message)
		return;
	}
	
	// del all
	if (all)
	{
		reset_spawn()
	}
	// del newest points
	else
	{
		static Float:reset[4]
		g_total_spawns --
		g_spawns[g_total_spawns] = reset
	}
}
create_line_point(id, const Float:start[3], const Float:end[3], const color[3])
{
	if (!is_user_connected(id)) return;
	
	new iStart[3], iEnd[3]
	FVecIVec(start, iStart)
	FVecIVec(end, iEnd)
	
	message_begin(MSG_ONE, SVC_TEMPENTITY, {0,0,0}, id)
	write_byte(TE_BEAMPOINTS)	// temp entity event
	write_coord(iStart[0])		// startposition: x
	write_coord(iStart[1])		// startposition: y
	write_coord(iStart[2])		// startposition: z
	write_coord(iEnd[0])		// endposition: x
	write_coord(iEnd[1])		// endposition: y
	write_coord(iEnd[2])		// endposition: z
	write_short(cache_spr_line)	// sprite index
	write_byte(0)			// start frame
	write_byte(0)			// framerate
	write_byte(10)			// life in 0.1's
	write_byte(15)			// line width in 0.1's
	write_byte(0)			// noise amplitude in 0.01's
	write_byte(color[0])		// color: red
	write_byte(color[1])		// color: green
	write_byte(color[2])		// color: blue
	write_byte(200)			// brightness
	write_byte(0)			// scroll speed in 0.1's
	message_end()
}
reset_spawn(t=0)
{
	for (new s=0; s<MAX_SPAWNS; s++)
	{
		for (new i=0; i<4; i++)
		{
			if (t) g_spawns_r[s][i] = 0
			else g_spawns[s][i] = 0.0
		}
	}
	if (!t) g_total_spawns = 0
}
is_point(Float:point[3])
{
	if (!point[0] && !point[1] && !point[2]) return 0
	return 1
}
color_saytext(player, const message[], any:...)
{
	new text[256]
	format(text, charsmax(text), "%s",message)
	format(text, charsmax(text), "%s",check_text(text))
	
	new dest
	if (player) dest = MSG_ONE
	else dest = MSG_ALL
	
	message_begin(dest, get_user_msgid("SayText"), {0,0,0}, player)
	write_byte(1)
	write_string(text)
	message_end()
}
check_text(text1[])
{
	new text[256]
	format(text, charsmax(text), "%s", text1)
	
	replace_all(text, charsmax(text), ">x04", "^x04")
	replace_all(text, charsmax(text), ">x03", "^x03")
	replace_all(text, charsmax(text), ">x01", "^x01")

	return text
}
spawn_check_dist(Float:origin[3], point=-1)
{
	new Float:originE[3], Float:origin1[3], Float:origin2[3]
	
	for (new i=0; i<g_total_spawns; i++)
	{
		if (i==point) continue;
		
		originE[0] = (g_spawns[i][0])
		originE[1] = (g_spawns[i][1])
		originE[2] = (g_spawns[i][2])
		
		// xoy
		origin1 = origin
		origin2 = originE
		origin1[2] = origin2[2] = 0.0
		if (vector_distance(origin1, origin2)<=2*16.0)
		{
			// oz
			origin1 = origin
			origin2 = originE
			origin1[0] = origin2[0] = origin1[1] = origin2[1] = 0.0
			if (vector_distance(origin1, origin2)<=100.0) return 0;
		}
	}

	return 1;
}
stock ChatColor(const id, const input[], any:...)
{
	new count = 1, players[32]
	static msg[191]
	vformat(msg, 190, input, 3)
    
	replace_all(msg, 190, "!g", "^4") 
	replace_all(msg, 190, "!y", "^1") 
	replace_all(msg, 190, "!r", "^3") 
	replace_all(msg, 190, "!b", "^0")
    
	if (id) players[0] = id; else get_players(players, count, "ch")
	{
		for (new i = 0; i < count; i++)
		{
			if (is_user_connected(players[i]))
			{
				message_begin(MSG_ONE_UNRELIABLE, get_user_msgid("SayText"), {0,0,0}, players[i])
				write_byte(players[i]);
				write_string(msg);
				message_end();
			}
		}
	}
}


#if defined DEBUG
public CREATOR_DEBUG_INFO(id)
{
	new WaveNum, SpawnNum, all_npc = npc_get_creatednum();
	
	if ( HUNTER_BOSS_CREATED || HUNTER_zombie_power >= WAVE_BEFORE_BOSS )
	{
		WaveNum = 666
		SpawnNum = 999
	}
	else
	{
		WaveNum = HUNTER_zombie_power
		SpawnNum = ZOMBIE_2_SPAWN
	}
	
	
	set_hudmessage(255, 255 , 255, -0.2,-0.9, 0, 0.01, 0.9, 0.3, 0.3 );
	show_hudmessage(0,  "%L",0, "SURVIVAL_MODE_DEBUG", 
	
	g_CONSTANT_SPAWNING,CONSTANT_FULL,
	WaveNum, g_counter, SpawnNum,
	GET_EVOLUTION(),
	all_npc
	
	);
}
#endif

public pfn_keyvalue(entid)
{
   new classname[32], key[32], value[32]
   copy_keyvalue(classname, 31, key, 31, value, 31)

   if ( equal(classname,"func_buyzone") && is_valid_ent(entid) )
      remove_entity(entid) 
      // remove all "func_buyzone" entity which limte buyzone range when map created at this moment.

   if (  is_valid_ent(entid) && equal(classname,"info_map_parameters") 
         && entity_get_int(entid,EV_INT_iuser1)!=1 )
   {  
      DispatchKeyValue(entid,"buying","0") // no limite team buy vaule
      if (__MAPCONFIG_Ent){
         remove_entity(__MAPCONFIG_Ent) // remove custom entity when map contains this class type
         __MAPCONFIG_Ent = 0
      }
   }
}



public Check_Respawn(id)
{
	if ( !get_pcvar_num( cvar_respawn) )
		return
		
	if ( id > 100500 )
		id -= 100500;

	if ( !is_user_connected(id) || is_user_alive(id) )
		return;
		
	if ( get_user_team( id ) == CS_TEAM_SPEC || get_user_team( id ) == CS_TEAM_UNASSIGNED )
		return;
	
	new resp_time = 30
	
	#if defined LA2A_SHOP
		if ( g_fast_respawn[id] ) resp_time = 15
	#endif
	
	if ( g_death_time[id] >= resp_time )
	{
		ExecuteHamB(Ham_CS_RoundRespawn, id); 
		set_user_godmode( id, 1 );
		set_task(5.0, "CTask__gmOFF", id+100500)
		g_death_time[id] = 0
		return
	}
	g_death_time[id]++
	set_hudmessage ( 190, 190, 190, 0.015, 0.15, 0, 0.01, 0.9, 0.3, 0.3 );
	show_hudmessage(id,  "%L",0, "RESPAWN_USER_IN", resp_time-g_death_time[id]);
}

public CTask__gmOFF(id)
{
	if ( id > 100500 )
		id -= 100500;

	if ( !is_user_alive(id) )
		return;
	set_user_godmode( id, 0 );
}
	


public User_Respawn(id) 
{
	new i, _continue = 0;
	for ( i=1; i < get_maxplayers(); i++ )
	{
		if ( is_user_alive(i) )
			_continue++
	}
	if ( !_continue )
	{
		npc_reset()
		set_dhudmessage(255, 50 , 50, 0.2,-0.5, 0, 6.01, 90.9, 0.3, 0.3 );
		show_dhudmessage(0,  "%L",0, "STRIKE_DEFEAT");
		set_task(6.0, "new_map")
	}
}

/*public CTask__Respawn(id) 
{
	if ( !get_pcvar_num( cvar_respawn) )
		return
		
	if ( id > 100500 )
		id -= 100500;

	if ( !is_user_connected(id) || is_user_alive(id) )
		return;
		
	if ( get_user_team( id ) == CS_TEAM_SPEC )
		return;
	
	new resp_time = 60
	
	#if defined LA2A_SHOP
		if ( g_fast_respawn[id] ) resp_time = 30
	#endif
	
	if ( g_death_time[id] >= resp_time )
	{
		ExecuteHamB(Ham_CS_RoundRespawn, id); 
		set_user_godmode( id, 1 );
		set_task(5.0, "CTask__gmOFF", id+100500)
		g_death_time[id] = 0
		return
	}
	g_death_time[id]++
	//set_task(1.0, "CTask__Respawn", id+100500);
	
	//set_dhudmessage(190, 190, 190	, -1.0, -1.0, 0, 0.01, 0.9, 0.3, 0.3 );
	//show_dhudmessage(id,  "%L",0, "RESPAWN_USER_IN", 60-g_death_time[id]);
	set_hudmessage ( 190, 190, 190, 0.015, 0.15, 0, 0.01, 0.9, 0.3, 0.3 );
	show_hudmessage(id,  "%L",0, "RESPAWN_USER_IN", 60-g_death_time[id]);
	
}*/
