public HumanWin()
{
	TerminateRound( RoundEndType_TeamExtermination,TeamWinning_Ct );
}

public ZombieBombExplosion(ent)
{
	if (!g_newround || g_endround) return
	static Float:originF[3]
	pev(ent, pev_origin, originF)
		
	message_begin(MSG_BROADCAST,SVC_TEMPENTITY)
	write_byte(TE_EXPLOSION)
	engfunc(EngFunc_WriteCoord,originF[0])
	engfunc(EngFunc_WriteCoord,originF[1])
	engfunc(EngFunc_WriteCoord,originF[2])
	write_short(cache_spr_zombiebomb_exp)
	write_byte(40)
	write_byte(30)
	write_byte(14)
	message_end()
		
	engfunc(EngFunc_EmitSound, ent, CHAN_WEAPON, ZOMBIEBOM_SOUND_EXP, 1.0, ATTN_NORM, 0, PITCH_NORM)
	static victim
	victim = -1
	new Float:fOrigin[3],Float:fDistance,Float:fDamage
	while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, ZOMBIEBOM_RADIUS)) != 0)
	{
		if (!is_user_alive(victim)) continue
		ScreenShake(victim)
		pev(victim, pev_origin, fOrigin)
		fDistance = get_distance_f(fOrigin, originF)
		fDamage = ZOMBIEBOM_POWER - floatmul(ZOMBIEBOM_POWER, floatdiv(fDistance, ZOMBIEBOM_RADIUS))//get the damage value
		fDamage *= EstimateDamage(originF, victim, 0)
		if ( fDamage < 0 ) continue
		CreateBombKnockBack(victim,originF,fDamage,ZOMBIEBOM_POWER)
	}
	set_pev(ent, pev_effects, EF_NODRAW);
	set_pev(ent, pev_flags, pev(ent, pev_flags) | FL_KILLME);
}
/*public client_damage(attacker,victim,damage,wpnindex,hitplace,TA)
{
	if (attacker == victim || g_zombie[attacker] || !g_zombie[victim]) return
	new damage_victim = get_user_health(victim)+damage
	new damage_fire = min(damage_victim, damage)
	UpdateEvolutionDamage(victim, damage_fire)
}*/
public Make_Zombie(id,iSetHeath)
{
	if (!is_user_alive(id)) return
	
	//server_print("Make Zombie %d",id)
	
	/*StripSlot(id, 1)
	StripSlot(id, 2)*/
	StripWeapons(id/*, 0*/)

	g_hero[id] = 0
	g_zombie[id] = 1


	//SetTeam(id, 1)
	//set_pdata_int(id, 114, 1);
	new Float:gravity, Float:speed, Float:xdamage, Float:xdamage2, Float:fKb
	gravity = ArrayGetCell(zombie_gravity, g_zombieclass[id])
	speed = ArrayGetCell(zombie_speed, g_zombieclass[id])
	xdamage = ArrayGetCell(zombie_xdamage, g_zombieclass[id])
	xdamage2 = ArrayGetCell(zombie_xdamage2, g_zombieclass[id])
	fKb = ArrayGetCell(zombie_knockback, g_zombieclass[id])
	g_zombie_xdamage[id][0] = xdamage
	g_zombie_xdamage[id][1] = xdamage2
	g_zombie_xdamage[id][2] = xdamage2
	g_fNextRestoreHealth[id] = get_gametime() + RESTORE_HEALTH_TIME;
	bte_wpn_set_knockback(id, fKb);
	bte_wpn_set_maxspeed(id, speed);
	set_pev(id, pev_gravity, gravity);
	
	bte_wpn_give_named_wpn(id,"knife",0)
	if(bte_fun_get_have_mode_item(id,4)) GiveZombieBomb(id)
	//bte_wpn_set_playerwpn_model(id,0,"",0,0)

	set_pdata_float(id, m_flNextAttack, 1.0);
	
	if(get_pcvar_num(Cvar_HolsterBomb))
	{
		client_cmd(id,"weapon_knife")
	}
	
	if(iSetHeath) UpdateHealthZombie(id,0)
	
	SetPlayerModel(id)
	SetZombieViewModel(id)
	// nvg
	g_nvg[id]=1
	//cmd_nightvision(id)
	Nvg(id)
	CheckEvolution(id)
	UpdateScoreBoard()
	
	//ExecuteForward(g_fwUserInfected, g_fwDummyResult, id, 0)
	
	//server_print("Make Zombie finished.")
}
public Make_Zombie2(id,Float:health)
{
	if (!is_user_alive(id)) return
	
	//server_print("Make Zombie %d",id)
	
	/*StripSlot(id, 1)
	StripSlot(id, 2)*/
	StripWeapons(id/*, 0*/)

	g_human[id] = 0
	g_hero[id] = 0
	g_zombie[id] = 1
	g_level[id] = 2
	
	//SetTeam(id, 1)
	
	set_pdata_int(id, 114, 1);
	
	remove_task(id + TASK_UPDATETEAM)
	set_task(0.1, "Task_UpdateTeam", id + TASK_UPDATETEAM)
	
	
	//PRINT("Set id:%d team:%d",id,get_pdata_int(id, 114));
	new Float:gravity, Float:speed, Float:xdamage, Float:xdamage2, Float:fKb
	gravity = ArrayGetCell(zombie_gravity, g_zombieclass[id])
	speed = ArrayGetCell(zombie_speed, g_zombieclass[id])
	xdamage = ArrayGetCell(zombie_xdamage, g_zombieclass[id])
	xdamage2 = ArrayGetCell(zombie_xdamage2, g_zombieclass[id])
	fKb = ArrayGetCell(zombie_knockback, g_zombieclass[id])
	g_zombie_xdamage[id][0] = xdamage
	g_zombie_xdamage[id][1] = xdamage2
	g_zombie_xdamage[id][2] = xdamage2
	g_fNextRestoreHealth[id] = get_gametime() + RESTORE_HEALTH_TIME;
	bte_wpn_set_maxspeed(id, speed)
	set_pev(id, pev_gravity, gravity)
	bte_wpn_set_knockback(id, fKb);
	
	if(bte_fun_get_have_mode_item(id,1)) health += 1000.0;
	
	g_zombie_health_start[id] = floatround(health)
	g_zombie_armor_start[id] = 500;
	
	set_pev(id, pev_max_health,health)
	set_pev(id, pev_health,health)
	set_pev(id,pev_armorvalue,health/10)

	
	if(bte_fun_get_have_mode_item(id,4)) GiveZombieBomb(id)
	Message_HudTextPro(id, "ZombiSelected")
	
	bte_wpn_give_named_wpn(id,"knife",1)
	//bte_wpn_set_playerwpn_model(id,0,"",0,0)
	
	if(get_pcvar_num(Cvar_HolsterBomb))
	{
		client_cmd(id,"weapon_knife")
	}

	set_pdata_float(id, m_flNextAttack, 1.0);
	
	SetPlayerModel(id)
	SetZombieViewModel(id)
	g_nvg[id]=1
	Nvg(id)
	CheckEvolution(id)
	UpdateScoreBoard()
	
	if (MH_IsMetaHookPlayer(id))
	{
		MH_PlayBink(id,"origin.bik",0.5,0.5,255,255,255,0,1,1,0)
	}
	

	//server_print("Make Zombie finished.")
}

public Make_Hero(id)
{
	if (!is_user_alive(id)) return
	
	//server_print("Make Hero %d",id)
	
	g_zombie[id] = 0
	g_hero[id] = 1
	
	//SetTeam(id, 2)
	/*set_pev(id,pev_health,1000.0)
	set_pev(id,pev_max_health,1000.0)
	set_pev(id,pev_armorvalue,100.0)*/
	//set_pev(id, pev_gravity, HERO_GRAVITY)
	g_nvg[id]=0
	g_havenvg[id] = 0
	
	SetPlayerModel(id)
	new sex = bte_get_user_sex(id)	
	if(sex==1)
	{
		bte_wpn_give_named_wpn(id,"svdex",1)
		bte_wpn_give_named_wpn(id,"ddeagle",1)
		MH_DrawTargaImage(id,"mode\\zb3\\hero",1,1,255,255,255,0.5,0.3,3,11,5.0)
	}
	else
	{
		bte_wpn_give_named_wpn(id,"qbarrel",1)
		bte_wpn_give_named_wpn(id,"ddeagle",1)
		MH_DrawTargaImage(id,"mode\\zb3\\heroine",1,1,255,255,255,0.5,0.3,3,11,5.0)
	}
	// !TODO TGA
	
	//
	message_begin(MSG_BROADCAST, g_msgScoreAttrib)
	write_byte(id) // id
	write_byte(1<<3) // attrib
	message_end()

	
	//server_print("Make Hero finished.")
}
public Make_Human(id)
{
	if (!is_user_alive(id)) return
	
	//server_print("Make Human %d",id)
	
	g_zombie[id] = 0
	g_hero[id] = 0
	g_human[id] = 1
	//SetTeam(id, 2)
	set_pev(id, pev_health,1000.0)
	set_pev(id, pev_max_health,1000.0)
	set_pev(id, pev_armorvalue,100.0)
	//PRINT("Set id:%d team:%d",id,get_pdata_int(id, 114));
	// fix some bugs
	if(!g_newround)
	{
		if(bte_fun_get_have_mode_item(id,1)) set_pev(id, pev_gravity, 0.8);
		else set_pev(id, pev_gravity, 1.0);
	}
	g_nvg[id]=0
	g_havenvg[id] = 0
	if(bte_fun_get_have_mode_item(id,3))
	{
		g_human_morale[id] = 3
		RenderingHuman(id);
	}
	else
	{
		g_human_morale[id] = 0
	}
	
	new itembit;
	
	for(new i=0;i<=2;i++)
		if(bte_fun_get_have_mode_item(id,i+1)) itembit |= 1<<i;
	
	MH_SendZB3Data(id, 4, itembit);
	MH_SendZB3Data(id, 12, 0);
	MH_SendZB3Data(id, 1, g_human_morale[0] + g_human_morale[id])
	
	//server_print("Make Human finished.")
}
public Make_First_Zombie()
{
	PlaySound(0,SND_BGM)
	new sound[64], sex
	new iInGame
	for(new i =1;i<33;i++)
	{
		if(is_user_connected(i) && is_user_alive(i)) iInGame++
	}
	if(!iInGame)
	{
		//PRINT("NO INGAME PLAYERS!")
		return
	}
	new iZombieNum = (iInGame - (iInGame % 10)) / 10 + 1;

	new Float:fMaxHealth;	
	fMaxHealth = 1000.0 * iInGame / iZombieNum;

	new iRan
	do
	{
		iRan = GetRandomPlayer(2)
		if(!iRan)
		{
			//PRINT("返回错误")
			return
		}
		// Set Info
		g_level[iRan] = 2
		if(!g_zombieclass[iRan]||is_user_bot(iRan)) g_zombieclass[iRan] = random(class_count)
		sex = bte_get_user_sex(iRan)
		if (sex == 2) ArrayGetString(sound_female_death, random(ArraySize(sound_female_death)), sound, charsmax(sound))
		else ArrayGetString(sound_human_death, random(ArraySize(sound_human_death)), sound, charsmax(sound))		
		
		PlayEmitSound(iRan, CHAN_VOICE, sound)		
		
		Make_Zombie2(iRan,fMaxHealth);
		ExecuteForward(g_fwUserInfected, g_fwDummyResult, iRan, 33);
		SetRendering(iRan)
		ShowZombieMenu(iRan)
		
	} while (--iZombieNum)
	
	ArrayGetString(sound_zombie_coming, random(ArraySize(sound_zombie_coming)), sound, charsmax(sound))
	PlaySound(0, sound)
	
	
	if(random_num(0, 5) > 1)
	{
		new szHeroMsg[128];

		new iZombieNum = 1;
		iZombieNum += random_num(0, iInGame / 10);
		iZombieNum += random_num(0, iInGame / 10 - 1);

		new iRan
		do
		{
			iRan = GetRandomPlayer(2)
			if(!iRan)
				return

			if(!g_hero[iRan]) Make_Hero(iRan)
			
		} while (--iZombieNum)
		

		new name[32]
		new iTotalHero = 0;
		new iSendMsg = 0;

		for (new id = 1; id <33; id++)
		{
			if (g_hero[id])
				iTotalHero += 1;
		}
	
		for (new id = 1; id <33; id++)
		{
			if (g_hero[id])
			{
				iTotalHero --
				get_user_name(id,name,31)
				format(szHeroMsg,127,"%s%s%s",szHeroMsg,name,iTotalHero?"，":"")
				iSendMsg = 1;
			}
		}
		format(szHeroMsg,127,"%L",LANG_PLAYER,"BTE_ZB3_HEROINFO",szHeroMsg)
		if(iSendMsg) client_print(0,print_center,szHeroMsg)
	}
	

	

	g_newround = 1


	for (new id = 1; id <33; id++)
	{
		if (is_user_connected(id) && !g_zombie[id] && !g_hero[id] && !g_human[id])
		{
			Make_Human(id)
		}
	}
	
	if (task_exists(TASK_SUPPLYBOX)) remove_task(TASK_SUPPLYBOX)
	set_task(SUPPLYBOX_TIME_FIRST, "Task_RespawnSupplyBox", TASK_SUPPLYBOX)
	if (task_exists(TASK_MAKEZOMBIE)) remove_task(TASK_MAKEZOMBIE)
	//UpdateScoreBoard()
}

public PlayerRandomSpawn(id)
{
	static hull, sp_index, i
	hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
	
	if (!g_spawnCount) return
	sp_index = random_num(0, g_spawnCount - 1)
	for (i = sp_index + 1;; i++)
	{
		if (i >= g_spawnCount) i = 0
		
		if (CheckHull(g_spawns[i][0], hull))
		{
			engfunc(EngFunc_SetOrigin, id, g_spawns[i][0])
			set_pev(id, pev_angles, g_spawns[i][1])
			set_pev(id, pev_v_angle, g_spawns[i][2])
			break
		}
		if (i == sp_index) break
	}	
}
public SupplyBoxRandomSpawn(id)
{
	static hull, sp_index, i
	hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN

	if (!g_spawnCount_box) return
	sp_index = random_num(0, g_spawnCount_box - 1)
	for (i = sp_index + 1;; i++)
	{
		if (i >= g_spawnCount_box) i = 0
		if (CheckHull(g_spawns_box[i], hull))
		{
			engfunc(EngFunc_SetOrigin, id, g_spawns_box[i])
			break;
		}
		if (i == sp_index) break;
	}
}
public ZombieInfectedHuman(attacker, victim)
{
	// show Msg Death
	SendDeathMsg(attacker, victim)
	FixDeadAttrib(victim)
	
	UpdateFrags(attacker, 1)
	UpdateDeaths(victim, 1)
	
	UpdateEvolution(attacker, victim)
	g_evolution[victim] = 0.0
	g_level[victim] = 1
	//if(bte_fun_get_have_mode_item(victim,1)) g_zombie_health_start[victim] = max(get_user_health(attacker), MIN_HEALTH_ZOMBIE_RANDOM);
	/*else */
	if(bte_fun_get_have_mode_item(victim,1))
	{
		g_zombie_health_start[victim] = max(floatround(get_user_health(attacker)*0.7), MIN_HEALTH_ZOMBIE_RANDOM);
		g_zombie_armor_start[victim] = floatround(get_user_armor(attacker)*0.7);
	}
	else
	{
		g_zombie_health_start[victim] = max(floatround(get_user_health(attacker)*0.5), MIN_HEALTH_ZOMBIE_RANDOM);
		g_zombie_armor_start[victim] = floatround(get_user_armor(attacker)*0.5);
	}
	/*g_zombie_armor_start[victim] = g_zombie_health_start[victim] /14 / 50;
	g_zombie_health_start[victim] /= 500;
	g_zombie_health_start[victim] *= 500;*/
	if(bte_fun_get_have_mode_item(victim,2)) g_zombie_health_start[victim] += 1000;
	//g_zombie_armor_start[victim] *= 50;
	if(bte_fun_get_have_mode_item(victim,2)) g_zombie_armor_start[victim] += 100;
	
	set_pdata_int(victim, 114, 1);
	
	remove_task(victim + TASK_UPDATETEAM)
	set_task(0.1, "Task_UpdateTeam", victim + TASK_UPDATETEAM)
	
	//SetTeam(victim, 1);
	
	if(!g_zombieclass[victim]||is_user_bot(victim)) g_zombieclass[victim] = random(class_count)
	Make_Zombie(victim,1)
	g_level[victim] = 1
	SetRendering(victim)
	new sound[64], sex
	sex = bte_get_user_sex(victim)
	if (sex == 2) ArrayGetString(sound_female_death, random(ArraySize(sound_female_death)), sound, charsmax(sound))
	else ArrayGetString(sound_human_death, random(ArraySize(sound_human_death)), sound, charsmax(sound))
	PlayEmitSound(victim, CHAN_VOICE, sound)
	ExecuteForward(g_fwUserInfected, g_fwDummyResult, victim, attacker)
	ShowZombieMenu(victim)
	//set_task(0.2, "Task_InfectedSound", victim+TASK_INFECTEDSOUND);
	InfectedSound()
	//MH_SendZB3Data(attacker,3,g_evolution[attacker])
	
	if (MH_IsMetaHookPlayer(victim))
	{
		MH_PlayBink(victim,"infection.bik",0.5,0.5,255,255,255,0,1,1,0)
	}
}
public HumanKilledZombie(killer, victim, headshot)
{
	if(victim<1 || victim>32 || !g_zombie[victim]) return
	if (!headshot)
	{
		//UpdateDeaths(victim, -1)
		g_respawning[victim] = 1
		if (task_exists(victim+TASK_ZOMBIE_RESPAWN)) remove_task(victim+TASK_ZOMBIE_RESPAWN)
		
		
		//respawn time
		if(bte_fun_get_have_mode_item(victim,3))
		{
			g_respawn_count[victim] = 2
			set_task(1.0, "Task_ZombieRespawn2", victim+TASK_ZOMBIE_RESPAWN,"",0,"a",2)
		}
		else
		{
			g_respawn_count[victim] = RESPAWN_TIME_WAIT + 2
			//client_print(victim, print_center,"%L",LANG_PLAYER,"BTE_ZB3_RESPAWN_WAITING",g_respawn_count[victim])
			set_task(1.0, "Task_ZombieRespawn", victim+TASK_ZOMBIE_RESPAWN,"",0,"a",7)
			if (task_exists(victim+TASK_ZOMBIE_RESPAWN_EF)) remove_task(victim+TASK_ZOMBIE_RESPAWN_EF)
			set_task(0.5, "Task_ZombieRespawnEffect", victim+TASK_ZOMBIE_RESPAWN_EF)
		}
		
		if(g_zombie_health_start[victim])
		{
			if(bte_fun_get_have_mode_item(victim,3))
			{
				g_zombie_armor_start[victim] = 0;
			}
			else
			{
				g_zombie_health_start[victim] = max(floatround(g_zombie_health_start[victim]*0.8),MIN_HEALTH_ZOMBIE_RANDOM);
				g_zombie_armor_start[victim] = floatround(g_zombie_armor_start[victim]*0.8);
			}
		}
		//g_zombie_armor_start[victim] *= 50;
		//g_zombie_armor_start[victim] -= 50;
		g_zombie_armor_start[victim] = 0;
		UpdateDeaths(victim, -1)
	}
	else
	{
		remove_task(victim+TASK_ZOMBIE_RESPAWN_EF)
		client_print(victim, print_center,"%L",LANG_PLAYER,"BTE_ZB3_RESPAWN_HEADSHOT")
		UpdateFrags(killer,3)
	}
	if(killer>0 && killer<33) // IF NORMAL KILLED
	{
		UpdateHumanLevel(0)
		UpdateScoreBoard()
		CheckWinCondition()
	}
}
public ZombieRespawn(id)
{
	if (!g_newround || g_endround || !is_user_connected(id)) return
	
	g_respawning[id] = 0
	if (is_user_connected(id))
	{
		ExecuteHamB(Ham_CS_RoundRespawn, id)
	}
	//Strip_Weapon(id)
	Make_Zombie(id,1)
	ExecuteForward(g_fwUserInfected, g_fwDummyResult, id, 0)
	
	new sound[64]
	ArrayGetString(sound_zombie_comeback, random(ArraySize(sound_zombie_comeback)), sound, charsmax(sound))
	//PlayEmitSound(id, CHAN_VOICE, sound)
	PlaySound(0, sound);
	ExecuteForward(g_fwUserInfected, g_fwDummyResult, id, 0)
	
	new Float:gravity, Float:speed
	gravity = ArrayGetCell(zombie_gravity, g_zombieclass[id])
	speed = ArrayGetCell(zombie_speed, g_zombieclass[id])
	bte_wpn_set_maxspeed(id, speed)
	set_pev(id, pev_gravity, gravity)
	
	SetPlayerModel(id);
	
	//SetTeam(id, 1);
	return
}

public CheckWinCondition()
{
	if(!Stock_GetPlayer(0))
	{
		SetBlockRound(0)
		TerminateRound( RoundEndType_TeamExtermination,TeamWinning_Terrorist )
	}
	else if(!CheckRespawning() && !Stock_GetPlayer(1))
	{
		SetBlockRound(0)
		TerminateRound( RoundEndType_TeamExtermination,TeamWinning_Ct )
	}
}
public CheckRespawning()
{
	for(new i = 1;i<33;i++)
	{
		if(is_user_connected(i) && g_zombie[i] && g_respawning[i]) return 1
	}
	return 0
}
