#include "bot.h"
#include "q_shared.h"
#include "m_player.h"

qboolean	pickup_pri;

int			targetindex;		//debugtarget
char		ClientMessage[MAX_STRING_CHARS];
botinfo_t	Bot[MAXBOTS];
route_t		Route[MAXNODES];
int			CurrentIndex;
int			SpawnWaitingBots;
float		JumpMax = 0;
qboolean	JmpTableChk = false;
float		JumpTable[FALLCHK_LOOPMAX];
int			botskill;
int			trace_priority;
int			skullindex;
int			headindex;
int			mpindex[MPI_INDEX];	//items in map
int			ListedBotCount;
gitem_t		*zflag_item;
edict_t		*zflag_ent;
int			zigflag_spawn;
int			ListedBots;
edict_t*	ExplIndex[MAX_EXPLINDEX];
edict_t*	LaserIndex[MAX_LASERINDEX];
/*-------------------------*/
//pre searched items
gitem_t	*Fdi_GRAPPLE;
gitem_t	*Fdi_BLASTER;
gitem_t *Fdi_SHOTGUN;
gitem_t *Fdi_SUPERSHOTGUN;
gitem_t *Fdi_MACHINEGUN;
gitem_t *Fdi_CHAINGUN;
gitem_t *Fdi_GRENADES;
gitem_t *Fdi_GRENADELAUNCHER;
gitem_t *Fdi_ROCKETLAUNCHER;
gitem_t *Fdi_HYPERBLASTER;
gitem_t *Fdi_RAILGUN;
gitem_t *Fdi_BFG;
gitem_t *Fdi_PHALANX;
gitem_t *Fdi_BOOMER;
gitem_t *Fdi_TRAP;

gitem_t *Fdi_SHELLS;
gitem_t *Fdi_BULLETS;
gitem_t *Fdi_CELLS;
gitem_t *Fdi_ROCKETS;
gitem_t *Fdi_SLUGS;
gitem_t *Fdi_MAGSLUGS;
/*--------------------------*/

/*
FIRE_PRESTAYFIRE
FIRE_STAYFIRE
FIRE_IGNORE
FIRE_REFUGE
FIRE_EXPAVOID
FIRE_QUADUSE
FIRE_AVOIDINV
FIRE_JUMPROC
*/
//combat flag set
int			FFlg[MAX_BOTSKILL]
=
{
//skill 0
	FIRE_PRESTAYFIRE | FIRE_STAYFIRE | FIRE_REFUGE,
//skill 1
	FIRE_REFUGE | FIRE_PRESTAYFIRE | FIRE_STAYFIRE | FIRE_REFUGE,
//skill 2
	FIRE_REFUGE | FIRE_PRESTAYFIRE | FIRE_IGNORE | FIRE_QUADUSE,
//skill 3
	FIRE_REFUGE | FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE,
//skill 4
	FIRE_REFUGE | FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE,
//skill 5
	FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE | FIRE_AVOIDINV | FIRE_IGNORE | FIRE_JUMPROC,
//skill 6
	FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE | FIRE_AVOIDINV | FIRE_IGNORE | FIRE_JUMPROC,
//skill 7
	FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE | FIRE_AVOIDINV| FIRE_IGNORE | FIRE_JUMPROC,
//skill 8
	FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE | FIRE_AVOIDINV| FIRE_IGNORE | FIRE_JUMPROC,
//skill 9
	FIRE_EXPAVOID | FIRE_IGNORE | FIRE_QUADUSE | FIRE_AVOIDINV| FIRE_IGNORE | FIRE_JUMPROC
};

qboolean BotApplyStrength(edict_t *ent)
{
	static gitem_t *tech = NULL;

	if (!tech)
		tech = FindItemByClassname("item_tech2");
	if (tech && ent->client 
		&& ent->client->pers.inventory[ITEM_INDEX(tech)]) 
		return true;

	return false;
}
qboolean BotApplyResistance(edict_t *ent)
{
	static gitem_t *tech = NULL;

	if (!tech)
		tech = FindItemByClassname("item_tech1");
	if (tech && ent->client 
		&& ent->client->pers.inventory[ITEM_INDEX(tech)]) 
		return true;

	return false;
}

//return foundedenemy
int Bot_SearchEnemy (edict_t *ent)
{
	zgcl_t		*zc;		//zc's address
	qboolean	tmpflg;		//temporary	
	edict_t		*target,*trent;
	trace_t		rs_trace;

	int		i,j,k;
	int		foundedenemy;

	float	pitch,yaw;
	float	vr,hr;

	char	*entcln;

	vec3_t	trmin;

	zc = &ent->client->zc;

	vr = (float)Bot[zc->botindex].param[BOP_VRANGE];
	hr = (float)Bot[zc->botindex].param[BOP_HRANGE];	

	if(vr > 180) vr = 180;
	if(hr > 180) hr = 180;
	if(vr < 10) vr = 10;
	if(hr < 10) hr = 10;
	//-------------------------------------------
	//search for enemy
	foundedenemy = 0;
	target = NULL;

	tmpflg = false;	//viewable flag
	if(zc->first_target != NULL){
		if(	Bot_trace(ent,zc->first_target)){
			tmpflg = true;
			foundedenemy++;
		}
	}

//	if(zc->ctfstate == CTFS_SUPPORTER) zc->ctfstate = CTFS_OFFENCER;

	// blue or red?
	if(ctf->value)
	{
		if(ent->client->resp.ctf_team == CTF_TEAM1) k = ITEM_INDEX(FindItem("Blue Flag"));
		else k = ITEM_INDEX(FindItem("Red Flag"));
	}
	else k = ITEM_INDEX(FindItem("ZB Flag"));

	// decide da sorting first or last
	if(random() < 0.5) j = 0;
	else j = -1;

	if(ent->client->pers.inventory[ITEM_INDEX(zflag_item)])
	{
		ent->client->zc.tmplstate = TMS_LEADER;
		ent->client->zc.followmate = NULL;	
	}

	for ( i = 1 ; i <= maxclients->value && target == NULL ; i++)
	{
		if(j){
			entcln = g_edicts[i].classname;
			trent =  &g_edicts[i];
		}
		else{
			entcln = g_edicts[(int)(maxclients->value) - i +1].classname;
			trent =  &g_edicts[(int)(maxclients->value) - i +1];					
		}

		if(!trent->inuse || ent == trent || zc->first_target == trent ||trent->deadflag) continue;

		if( entcln[0] == 'p' && trent->movetype != MOVETYPE_NOCLIP ){
			if(Bot_traceS(ent,trent))
			{
				VectorSubtract (trent->s.origin, ent->s.origin, trmin);
				//not ctf mode and sameteam
				if(!ctf->value && OnSameTeam(ent,trent))
				{
					if(trent->client->zc.first_target)
					{
						if(Bot_traceS(ent,trent->client->zc.first_target)) target = trent->client->zc.first_target;
					}
					if(trmin[2] < JumpMax && VectorLength(trmin) < 400)
					{
						yaw = (float)Bot[ent->client->zc.botindex].param[BOP_TEAMWORK];
						if(trent->client->pers.inventory[ITEM_INDEX(zflag_item)])
						{
							trent->client->zc.tmplstate = TMS_LEADER;
							trent->client->zc.followmate = NULL;
							if((9 * random()) < yaw)
							{
								ent->client->zc.tmplstate = TMS_FOLLOWER;
								ent->client->zc.followmate = trent;
							}
						}
						else 
						{
							if((9 * random()) < yaw)
							{
//gi.bprintf(PRINT_HIGH,"Team stateON\n");
								//相手がリーダー
								if(trent->client->zc.tmplstate == TMS_LEADER)
								{
									trent->client->zc.followmate = NULL;
									if(ent->client->zc.tmplstate == TMS_LEADER)
									{
										if(random() < 0.5)
										{
											ent->client->zc.tmplstate = TMS_FOLLOWER;
											ent->client->zc.followmate = trent;
										}
										else
										{
											ent->client->zc.tmplstate = TMS_LEADER;
											ent->client->zc.followmate = NULL;
											trent->client->zc.tmplstate = TMS_FOLLOWER;
											trent->client->zc.followmate = ent;											
										}
									}
									else
									{
										ent->client->zc.tmplstate = TMS_FOLLOWER;
										ent->client->zc.followmate = trent;									
									}
								}
								else
								{
									if(ent->client->zc.tmplstate == TMS_LEADER
										|| random() < 0.5)
									{
										ent->client->zc.tmplstate = TMS_LEADER;
										ent->client->zc.followmate = NULL;
										trent->client->zc.tmplstate = TMS_FOLLOWER;
										trent->client->zc.followmate = ent;										
									}
									else 
									{
										ent->client->zc.tmplstate = TMS_FOLLOWER;
										ent->client->zc.followmate = trent;
										trent->client->zc.tmplstate = TMS_LEADER;
										trent->client->zc.followmate = NULL;										
									}
								}
							}
						}
					}
				}
				else if(ctf->value && ent->client->resp.ctf_team == trent->client->resp.ctf_team)
				{
					//have flag
					if(trent->client->pers.inventory[k])
					{
						if(ent->client->zc.ctfstate == CTFS_OFFENCER)
						{
							ent->client->zc.ctfstate = CTFS_SUPPORTER;
							ent->client->zc.followmate = trent;
						}
						// if carrier have enemy
						if(trent->client->zc.first_target != NULL)
						{
							if(trent->client->zc.first_target->classname[0] == 'p')	
							{
								target = trent->client->zc.first_target;
							}
						}
						// if carrier tracing route
						if(trent->client->zc.route_trace && (trent->client->zc.routeindex - 2) > CurrentIndex)	
						{
							zc->routeindex = trent->client->zc.routeindex - 2;
						}
//						ent->s.angles[YAW] = Get_yaw (trmin);
//						if(ent->client->zc.ctfstate == CTFS_SUPPORTER ){
//							zc->first_target = NULL;
//							break;
//						}
					}
				}
				else 
				{
					foundedenemy++;
					if(!tmpflg && target == NULL)
					{
						pitch = Get_pitch(trmin);
						pitch = fabs(pitch - ent->s.angles[PITCH]);
						if(pitch > 180) pitch = 360 - pitch;
						//if(ent->client->zc.zcstate & STS_WAITS) target = trent;
						if(pitch <= vr)
						{ 
							yaw = Get_yaw(trmin);
							yaw = fabs(yaw - ent->s.angles[YAW]);
							if(yaw > 180) yaw = 360 - yaw;
							if(yaw <= hr || (ent->client->zc.zcstate & STS_WAITS))	target = trent;
						}
					}
					//
					if(!tmpflg && target == NULL && trent->mynoise && trent->mynoise2)
					{
						if(Bot[ent->client->zc.botindex].param[BOP_NOISECHK])
						{
							if(trent->mynoise->teleport_time >= (level.time - FRAMETIME))
							{
								VectorSubtract (trent->mynoise->s.origin, ent->s.origin, trmin);
								if(VectorLength(trmin) < 300)
								{
									pitch = (float)Bot[ent->client->zc.botindex].param[BOP_REACTION];
									if((9 * random()) < pitch) target = trent;
								}
							}
							if(target == NULL && trent->mynoise2->teleport_time >= (level.time - FRAMETIME))
							{
								VectorSubtract (trent->mynoise->s.origin, ent->s.origin, trmin);
								if(VectorLength(trmin) < 100)
								{
									pitch = (float)Bot[ent->client->zc.botindex].param[BOP_REACTION];
									if((9 * random()) < pitch) target = trent;									
								}								
							}
						}
					}
				}
			}
			//音のみで場所を判断
			else
			{
				if(Bot[ent->client->zc.botindex].param[BOP_NOISECHK]
					&& Bot[ent->client->zc.botindex].param[BOP_ESTIMATE]
					&& !tmpflg && trent->mynoise)
				{

					if(trent->mynoise->teleport_time >= (level.time - FRAMETIME))
					{
						AngleVectors (trent->client->v_angle, trmin, NULL, NULL);
						VectorScale(trmin,200,trmin);
						VectorAdd(trent->s.origin,trmin,trmin);
						rs_trace = gi.trace(trent->s.origin,NULL,NULL,trmin,trent,MASK_SHOT);
					
						VectorSubtract (ent->s.origin, rs_trace.endpos, trmin);
						if(VectorLength(trmin) < 500)
						{
							VectorCopy(rs_trace.endpos,trmin);
							rs_trace = gi.trace(ent->s.origin,NULL,NULL,trmin,ent,MASK_SHOT);
							pitch = (float)Bot[ent->client->zc.botindex].param[BOP_REACTION];
							
							if(rs_trace.fraction == 1.0 && (9 * random()) < pitch)
							{
								target = trent;
								ent->client->zc.battlemode |= FIRE_ESTIMATE;
								VectorCopy(trmin,ent->client->zc.vtemp);
							}
						}
					}
				}
			}
		}
	}
	if(target && !tmpflg) zc->first_target = target;
	else if(target && zc->first_target) 
	{
		if(Get_KindWeapon(target->client->pers.weapon) > 
			Get_KindWeapon(zc->first_target->client->pers.weapon)) zc->first_target = target;
	}
//	ent->client->zc.zcstate &= ~CTS_COMBS;	//clear combat state

	return (foundedenemy);
}

void Bot_SearchItems (edict_t *ent)
{
	zgcl_t		*zc;		//zc's address
	qboolean	wstayf,q;		//weaponflag	
	edict_t		*target,*trent;

	vec3_t		touchmin,touchmax;
	vec3_t		trmin,trmax;

	gitem_t		*item;
	char		*entcln;

	float		x,yaw;			//temporary
		
	int			i,j,k,conts;

	trace_t		rs_trace;

	zc = &ent->client->zc;


	if((zc->tmpcount++) & 1) return;

	j = 0;
	q = false;//rocket jump needed
	//search Items
	if(ctf->value)
	{
		if(ent->moveinfo.state == SUPPORTER) j = -1;
		else if( ent->target_ent != NULL)
		{
			if( ent->moveinfo.state == CARRIER && ent->target_ent->classname[6] == 'F') j = -1;
		}
		else if( ent->client->ctf_grapple != NULL) j = -1;
	}
	trent = zc->second_target;
	if( trent != NULL && !j )
	{
		x = random();
		if( trent->classname[0] == 'w') j = -1;
		else if( trent->classname[0]=='i'){
			if( trent->classname[5]=='q'
				|| trent->classname[5]=='f'
				|| trent->classname[5]=='t'
				|| trent->classname[5]=='i')
				j = -1;
		}
		else if((trent->classname[0] == 'p' && x > 0.2)
			|| ent->client->ctf_grapple != NULL	)
				j= -1;
	}

	if( j == 0 )
	{
		if ((int)(dmflags->value) & DF_WEAPONS_STAY) wstayf = true;
		else wstayf = false;

		target = NULL;
		VectorCopy (ent->absmin, touchmin);
		VectorCopy (ent->absmax, touchmax);
		
		// when ctf
		if(0/*ctf->value*/){
			touchmin[0] -= 500;
			touchmin[1] -= 500;
			touchmin[2] -= 500;
			touchmax[0] += 500;
			touchmax[1] += 500;
			touchmax[2] += 598;
		}
		// when not
		else
		{
			touchmin[0] -= 300;
			touchmin[1] -= 300;
			touchmin[2] -= 300;
			if(ent->waterlevel) touchmin[2] -= 200;
			touchmax[0] += 300;
			touchmax[1] += 300;
			touchmax[2] += 54;// +290);

			if(ent->health > 70 && ent->client->pers.inventory[ITEM_INDEX(Fdi_ROCKETLAUNCHER/*FindItem("Rocket Launcher")*/)])
			{
				i = ITEM_INDEX(Fdi_ROCKETS/*FindItem("Rockets")*/);
		
				if(ent->client->pers.inventory[i] > 0)
				{
					q = true;
					touchmax[2] += 290;
				}
			}
		}


		if((level.framenum - ent->client->resp.enterframe ) % 64 > 32) j = 0;
		else j = -1;

		k = globals.num_edicts + maxclients->value+1;

		for ( i=maxclients->value+1 ; i<globals.num_edicts ; i++)
		{
			if(j)	//normal
			{
				trent = &g_edicts[i];
				entcln = trent->classname;
			}
			else	//reverse
			{
				trent = &g_edicts[k - i];
				entcln = trent->classname;
			}

			if(!trent->inuse) continue;
			if(trent->solid != SOLID_TRIGGER)
			{
				if( ent->client->weaponstate == WEAPON_READY && !ent->client->zc.route_trace)
				{
					if( entcln )
					{
						if(entcln[0] == 'f' /*&& trent->classname[5] == 'b'*/
							&& trent->health //&&trent->moveinfo.state == PSTATE_BOTTOM
							&& trent->takedamage)//trent->moveinfo.wait == 0)
						{
							if(trent->classname[5] == 'b' 
								&& trent->monsterinfo.attack_finished > level.time) continue;

							trmax[0] = (trent->absmin[0] + trent->absmax[0]) / 2;
							trmax[1] = (trent->absmin[1] + trent->absmax[1]) / 2;
							trmax[2] = (trent->absmin[2] + trent->absmax[2]) / 2;							
							rs_trace = gi.trace (ent->s.origin, NULL, NULL, trmax ,ent, MASK_SHOT);

							if(rs_trace.ent == trent)
							{
					//		gi.bprintf(PRINT_HIGH,"kkkkkkk\n");
					//		continue;
								VectorSubtract (trmax, ent->s.origin,trmin);
								item = Fdi_BLASTER;//FindItem("Blaster");
//								ent->client->ammo_index = 0;
								item->use(ent,item);
								//ent->client->ammo_index = 0;
								//ent->client->pers.weapon = FindItem("Blaster");
								//ShowGun(ent);
								ent->s.angles[YAW] = Get_yaw(trmin);
								ent->s.angles[PITCH] = Get_pitch(trmin);
								ent->client->buttons |= BUTTON_ATTACK;
								ent->client->zc.objshot = true;
							}	 
						}
					}
				}
				continue;
			}

			


			if(trent->absmax[0]	< touchmin[0]) continue;
			if(touchmax[0]		< trent->absmin[0])	continue;
			if(trent->absmax[1]	< touchmin[1]) continue;
			if(touchmax[1]		< trent->absmin[1])	continue;
			if(trent->absmax[2]	< touchmin[2]) continue;
			if(touchmax[2]		< trent->absmin[2])	continue;			

			VectorSubtract (trent->s.origin, ent->s.origin, trmin);
			yaw = VectorLength(trmin);

/*			if( trent->classname[0] == 'w' || trent->classname[0] == 'R') x = 0;
			else if(trent->classname[0]=='i')
			{
				if(trent->classname[5]=='q'
					|| trent->classname[5]=='f'
					|| trent->classname[5]=='t'
					|| trent->classname[5]=='i') x = 0;
			}*/
			/*else*/ if( !ctf->value )	
			{
//				if(yaw >300 /*|| (trent->s.origin[2] - ent->s.origin[2] ) < -64*/)	continue;
			}

			if( Bot_trace(ent,trent) )
			{
				if(entcln[0] == 'i')
				{
					if(entcln[5] == 'h')
					{
						if(Q_stricmp (entcln, "item_health") == 0 )
						{
							if( ent->health < 100 && (!pickup_pri || yaw < 96)) target = trent;
						}
						else if(entcln[12] == 's'){ //item_health_small
							if(fabs(trent->s.origin[2] - ent->s.origin[2] + 8) > JumpMax) continue;
							target = trent;
						}
						else if(entcln[12] == 'l') //item_health_large
						{
							if( ent->health < 100 && (!pickup_pri || yaw < 96)) target = trent;
						}
						else if(entcln[12] == 'm') //item_health_mega
							target = trent;
					}
					else if(entcln[5] == 'a' && !pickup_pri)
					{
						if(entcln[11] == 's'){		//item_armor_shard 
							if(fabs(trent->s.origin[2] - ent->s.origin[2] + 8) > JumpMax) continue;
							target = trent; 
						}
						else if(entcln[11] == 'j')	//item_armor_jacket
						{
							if( ent->client->pers.inventory[ITEM_INDEX(FindItem("Jacket Armor"))] < 50 ) target = trent; 
						}
						else if(entcln[11] == 'c')	//item_armor_combat
						{
							if( ent->client->pers.inventory[ITEM_INDEX(FindItem("Combat Armor"))] < 100) target = trent; 
						}
						else if(entcln[11] == 'b')	//item_armor_body
						{
							if( ent->client->pers.inventory[ITEM_INDEX(FindItem("Body Armor"))] < 200) target = trent; 
						}
						else if(entcln[6] == 'd')	//item_adrenaline 
										target = trent; 
						else if(entcln[6] == 'n')	//item_ancient_head
										target = trent; 
					}
					else if(entcln[5] == 'f')
					{
						if( trent->spawnflags & DROPPED_ITEM ) target = trent;
						else if(entcln[10] == 't' && entcln[14] == '1')
						{ 
							if( ent->client->resp.ctf_team == CTF_TEAM2) target = trent;
							else if( ent->client->pers.inventory[ITEM_INDEX(FindItem("Blue Flag"))]) target = trent;
						}
						else if(entcln[10] == 't' && entcln[14] == '2')
						{ 
							if( ent->client->resp.ctf_team == CTF_TEAM1) target = trent; 			
							else if(ent->client->pers.inventory[ITEM_INDEX(FindItem("Red Flag"))]) target = trent;
						}
					}
					else if(entcln[5] == 't')
					{
						if(!BotApplyResistance(ent)) 
							if(	!BotApplyStrength(ent))
								if( !CTFApplyHaste(ent))
									if( !CTFHasRegeneration(ent)) target = trent;								
					}
					else
					{
						if(entcln[5] == 'q')		//item_quad 
							target = trent; 
						else if(entcln[5] == 'p' && entcln[6] == 'a')	//item_pack 
							target = trent; 
						else if(entcln[5] == 'b' && entcln[6] == 'a')	//item_bandolier 
							target = trent; 
						else if(entcln[5] == 'e')	//item_enviro 
							target = trent; 
						else if(entcln[5] == 'b')	//item_breather 
							target = trent; 
						else if(entcln[5] == 's')	//item_silencer 
							target = trent; 
						else if(entcln[5] == 'i')	//item_invulnerability 
							target = trent; 
						else if(entcln[5] == 'p' && entcln[12] == 'h')	//Q_stricmp (entcln, "item_power_shield") == 0) 
							target = trent; 
						else if(entcln[5] == 'p' && entcln[12] == 'c')	//Q_stricmp (entcln, "item_power_screen") == 0) 
							target = trent; 
					}
				}
				else if(entcln[0] == 'a' && !pickup_pri)
				{
					if(entcln[5] == 'b')							//ammo_bullets
					{
						if( ent->client->pers.inventory[ITEM_INDEX(Fdi_BULLETS/*FindItem("Bullets")*/)]
											< ent->client->pers.max_bullets) target = trent;
					}
					else if(entcln[5] == 's' && entcln[6] == 'h')	//ammo_shells
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_SHELLS/*FindItem("Shells")*/)]
											< ent->client->pers.max_shells) target = trent;
					}
					else if(entcln[5] == 'g')						//ammo_grenades
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_GRENADES/*FindItem("Grenades")*/)]
											< ent->client->pers.max_grenades) target = trent;
					}
					else if(entcln[5] == 'r')						//ammo_rockets
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_ROCKETS/*FindItem("Rockets")*/)]
											< ent->client->pers.max_rockets) target = trent;
					}
					else if(entcln[5] == 's' )						//ammo_slugs
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_SLUGS/*FindItem("Slugs")*/)]
											< ent->client->pers.max_slugs) target = trent;
					}
					else if(entcln[5] == 'c' )						//ammo_cells
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_CELLS/*FindItem("Cells")*/)]
											< ent->client->pers.max_cells) target = trent;
					}
					else if(entcln[5] == 'm' )						//ammo_magslug
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_MAGSLUGS/*FindItem("Mag Slug")*/)]
											< ent->client->pers.max_magslug) target = trent;
					}
					else if(entcln[5] == 't' )						//ammo_trap
					{
						if(ent->client->pers.inventory[ITEM_INDEX(Fdi_TRAP/*FindItem("Trap")*/)]
											< ent->client->pers.max_trap) target = trent;
					}
				}
				else if(entcln[0] == 'w')
				{
					if(entcln[7] == 's' && entcln[8] == 'h' )	//weapon_shotgun
					{
						if(!wstayf || (wstayf && !pickup_pri 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_SHOTGUN/*FindItem("Shotgun")*/)] 
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM) ) )) target = trent;
					}
					else if(entcln[7] == 's')					//weapon_supershotgun
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_SUPERSHOTGUN/*FindItem("Super Shotgun")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) ) target = trent;
					}
					else if(entcln[7] == 'm')					//weapon_machinegun
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_MACHINEGUN/*FindItem("Machinegun")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;
					}
					else if(entcln[7] == 'c')					//weapon_chaingun
					{
						if(!wstayf || (wstayf 
								&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_CHAINGUN/*FindItem("Chaingun")*/)]
								|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM))) ) target = trent;
					}
					else if(entcln[7] == 'g')					//weapon_grenadelauncher
					{
						if(!wstayf || (wstayf 
						&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_GRENADELAUNCHER/*FindItem("Grenade Launcher")*/)]
						|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;
					}
					else if(entcln[7]=='r' && entcln[8] == 'o')	//weapon_rocketlauncher
						{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_ROCKETLAUNCHER/*FindItem("Rocket Launcher")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;
					}
					else if(entcln[7] == 'h')					//weapon_hyperblaster
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_HYPERBLASTER/*FindItem("HyperBlaster")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;
					}
					else if(entcln[7] == 'r')					//weapon_railgun
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_RAILGUN/*FindItem("Railgun")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;	
					}
					else if(entcln[7] == 'b' && entcln[8] == 'o')//weapon_boomer
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_BOOMER/*FindItem("Ionripper")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;					
					}
					else if(entcln[7] == 'p')					//weapon_phalanx
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_PHALANX/*FindItem("Phalanx")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;	
					}
					else if(entcln[7] == 'b')					//weapon_bfg
					{
						if(!wstayf || (wstayf 
							&& (!ent->client->pers.inventory[ITEM_INDEX(Fdi_BFG/*FindItem("BFG10K")*/)]
							|| trent->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)))) target = trent;					
					}
				}
				else if(entcln[0] == 'R' && !ent->client->zc.route_trace)
				{
					if(entcln[2] == 'n')
					{
						if(ctf->value)
						{
							if(ent->moveinfo.state == CARRIER)
							{
								if(random() < 0.05) target = trent;
							}
							else if(ent->moveinfo.state == DEFENDER)
							{
								if(random() < 0.01) target = trent;
							}
							else if(random() < 0.02) target = trent;
						}
						else if(random() < 0.4)	target = trent;
					}
					else if(ent->client->zc.route_trace)
					{
						if(ent->client->zc.routeindex < CurrentIndex)
						{
							if(entcln[6] == 'X' && Route[ent->client->zc.routeindex].state == GRS_ONTRAIN) target = trent;
							else if(entcln[6] == '2' && Route[ent->client->zc.routeindex].state == GRS_PUSHBUTTON
								&& Route[ent->client->zc.routeindex].ent == trent) target = trent;
							else target = NULL;
						}
					}
					else if(entcln[6] == '3') target = NULL;
				}
			}
			// founded!
/*			if( target != NULL && !ctf->value)
			{
				if(!ent->waterlevel)
				{
					VectorSubtract(target->s.origin,ent->s.origin,touchmax);
					x = touchmax[2];
					touchmax[2] = 0;
					iyaw = VectorLength(touchmax);
					if( x < -39 ) 
					{
						yaw = iyaw/(-x);*/
//						if( /*yaw < 0.5 &&*/ yaw > 2.5 /*&& iyaw > 64*/) target = NULL;
/*						if(target != NULL)
						{
							if((target->spawnflags & (DROPPED_ITEM | DROPPED_PLAYER_ITEM)) && x < -64) target = NULL;
						}
					}
					if(target != NULL && !ent->waterlevel && x < -60)
					{
						if( target->classname[0] == 'w'
							|| (target->classname[0]=='i' && target->classname[5]=='q')
							|| (target->classname[0]=='i' && target->classname[5]=='f')
							|| (target->classname[0]=='i' && target->classname[5]=='t')
							|| (target->classname[0]=='i' && target->classname[5]=='i')) 
						{
							if(iyaw < 64 ) target = NULL;
						}
						else target = NULL;
					}
				}
			}
*/
			if(target != NULL)
			{
				conts = gi.pointcontents (target->s.origin);
				if(conts & CONTENTS_LAVA) target = NULL;
				else if((conts & CONTENTS_SLIME) && ent->client->enviro_framenum <= level.framenum) target = NULL;
			}
			if(target != NULL && !ctf->value )
			{
				if((target->s.origin[2] - ent->s.origin[2]) > 32  && !q)
				{
					x = target->moveinfo.start_origin[2] - ent->s.origin[2];
					if(x > 54 || x < -24) target = NULL;
					else 
					{
						x = target->s.origin[2] - target->moveinfo.start_origin[2];
						if(x > 54 || x < 0) target = NULL;
					}
				}
				else if((target->s.origin[2] - ent->s.origin[2]) <= 100  && q)
				{
					target = NULL;				
				}
			}

			if(target != NULL )
			{
				if(	zc->second_target == NULL )
				{
					zc->second_target = target;
					break;
				}
				else if(zc->second_target->classname[6] == 'F' &&
					zc->second_target->classname[6] == 'F')
				{
					target = NULL;
					continue;
				}
				else
				{
					if( (target->classname[0] == 'R' && target->classname[0] != 'F')
						|| target->classname[0] == 'w'
						|| (target->classname[0]=='i' && target->classname[5]=='q')
						|| (target->classname[0]=='i' && target->classname[5]=='t')
						|| (target->classname[0]=='i' && target->classname[5]=='f')
						|| (target->classname[0]=='i' && target->classname[5]=='i')) 
					{
						VectorSubtract (ent->s.origin, target->s.origin, trmin);
						if(ctf->value 
							&& zc->second_target->classname[6] == 'F'
							&& ent->moveinfo.state != CARRIER)
						{
							zc->second_target = target;
							break;
						}
						else if( VectorLength(trmin) > 24 )
						{
							zc->second_target = target;
							break;
						}
					}
				}
			}
			target = NULL;
		}
	}
}

//-----------------------------------------------------------------------------------------
//バクハツ物回避
//Avoid explotion		
//
#define EXPLO_BOXSIZE	64
qboolean Bot_ExploAvoid(edict_t *ent,vec3_t	v)
{
	int	i;

	vec3_t	absmax,absmin;
	vec3_t	msmax,msmin;

	if(ent->groundentity == NULL && !ent->waterlevel) return true;
	if(!(FFlg[Bot[ent->client->zc.botindex].param[BOP_COMBATSKILL]] & FIRE_EXPAVOID)) return true;
	
	VectorCopy(v,msmax);
	VectorCopy(v,msmin);
	msmax[0] += ent->maxs[0]; msmax[1] += ent->maxs[1]; msmax[2] += ent->maxs[2];
	msmin[0] += ent->mins[0]; msmin[1] += ent->mins[1]; msmin[2] += ent->mins[2];

	for(i = 0;i < MAX_EXPLINDEX;i++)
	{
		if(ExplIndex[i] != NULL) {if(ExplIndex[i]->inuse == false) ExplIndex[i] = NULL;}
		if(ExplIndex[i] != NULL) 
		{
			VectorCopy(ExplIndex[i]->s.origin,absmax);
			VectorCopy(absmax,absmin);
			absmax[0] += EXPLO_BOXSIZE; absmax[1] += EXPLO_BOXSIZE; absmax[2] += EXPLO_BOXSIZE;
			absmin[0] -= EXPLO_BOXSIZE; absmin[1] -= EXPLO_BOXSIZE; absmin[2] -= EXPLO_BOXSIZE;

			if(absmax[0]	< msmin[0]) continue;
			if(msmax[0]	< absmin[0])	continue;
			if(absmax[1]	< msmin[1]) continue;
			if(msmax[1]	< absmin[1])	continue;
			if(absmax[2]	< msmin[2]) continue;
			if(msmax[2]	< absmin[2])	continue;

			return false;
		}
	}
	return true;
}

//レーザーのチェック
qboolean CheckLaser(vec3_t pos,vec3_t maxs,vec3_t mins)
{
	int	i;
	vec3_t v,end,absmax,absmin;
	float L1,L2,L3;

	VectorAdd(pos,maxs,absmax);
	VectorAdd(pos,mins,absmin);

	for(i = 0;i < MAX_LASERINDEX;i++)
	{
		if(LaserIndex[i] == NULL) return false;
		if (!(LaserIndex[i]->spawnflags & 1)) continue;

		VectorSubtract(pos,LaserIndex[i]->s.origin,v);
		L1 = VectorLength(v);
		VectorSubtract(pos,LaserIndex[i]->moveinfo.end_origin,v);
		L2 = VectorLength(v);

		VectorSubtract(LaserIndex[i]->s.origin,LaserIndex[i]->moveinfo.end_origin,v);
		L3 = VectorLength(v);

//		VectorCopy (LaserIndex[i]->s.origin, start);
		VectorMA (LaserIndex[i]->s.origin, L3 * L1 / (L1 + L2), LaserIndex[i]->movedir, end);

		VectorSubtract(pos,end,v);
		L3 = VectorLength(v);
		
		if(L3 > L1 || L3 > L2) continue;

//gi.bprintf(PRINT_HIGH,"Length %f!\n",L3);

		if(end[0]	< absmin[0]) continue;
		if(absmax[0]	< end[0])	continue;
		if(end[1]	< absmin[1]) continue;
		if(absmax[1]	< end[1])	continue;
		if(end[2]	< absmin[2]) continue;
		if(absmax[2]	< end[2])	continue;
//gi.bprintf(PRINT_HIGH,"Laser Checked! %f\n",L3);
		return true;
	}
	return false;
}

//-----------------------------------------------------------------------------------------
// BOT移動可能判定new
// bot move test
//  return	false	can't 
//			true	stand
//			2		duck	
int Bot_moveT ( edict_t *ent,float ryaw,vec3_t pos,float dist,float *bottom)
{
	float		i,yaw;
	vec3_t		trstart,trend;
	vec3_t		trmin,trmax,v,vv;
	trace_t		rs_trace;
	float		tracelimit;
	qboolean	moveok;
	int			contents;

	int			tcontents;



	tcontents =/* MASK_BOTSOLID*/MASK_BOTSOLIDX;//MASK_PLAYERSOLID /*| CONTENTS_TRANSLUCENT*/;  //レーザーには触らない
//	if(!ent->waterlevel) tcontents |= CONTENTS_WATER;

	if(/*ent->client->zc.waterstate == WAS_FLOAT*/ent->waterlevel >= 1/*2*/) tracelimit = 75;//75;//61;
	else if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) tracelimit = 26;
	else tracelimit = JumpMax + 5;//61;

	VectorSet (trmin,-16,-16,-24);
	VectorSet (trmax,16,16,3);

	if(ent->client->zc.route_trace) VectorSet (vv,16,16,0);
	else VectorSet (vv,16,16,3);

	if(0/*!(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
		&& (ent->client->zc.n_duckedtime < FRAMETIME * 10 /*&& !ent->client->zc.route_trace)*/) trmax[2] = 31;
//	else if(ent->waterlevel && !ent->groundentity) trmax[2] = 32;
	else if(ent->client->zc.route_trace
		&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
		&& ent->waterlevel < 2)
	{
		Get_RouteOrigin(ent->client->zc.routeindex,v);
		if((v[2] - ent->s.origin[2]) > 20) trmax[2] = 31;
	}

	//移動先がどうなっているのか調べる
	yaw = ryaw*M_PI*2 / 360;
	trend[0] = cos(yaw) * dist ;				//start
	trend[1] = sin(yaw) * dist ;
	trend[2] = 0;
	VectorAdd (trend, ent->s.origin, trstart);

	VectorCopy(trstart,trend);
	trend[2] += 1;
	rs_trace = gi.trace (trstart, trmin, trmax, trend,ent, tcontents);
	
	trmax[2] += 1;
	if(rs_trace.allsolid || rs_trace.startsolid || rs_trace.fraction != 1.0)	//前には進めない場合
	{
		moveok = false;
		VectorCopy (trstart, trend);

		for( i = 4 ; i < (tracelimit + 4) ; i += 4 )
		{	
			trstart[2] = ent->s.origin[2] + i;
			rs_trace = gi.trace (trstart, trmin, vv/*trmax*/, trend,ent, tcontents );
//			rs_trace = gi.trace (trstart, trmin, trmax, trstart,ent, tcontents );
			if(!rs_trace.allsolid && !rs_trace.startsolid && rs_trace.fraction > 0)
			{
				moveok = true;
				break;
			}
		}
		if(!moveok/*i >= tracelimit+4*/)
//		if(i >= tracelimit - 4)
		{
//gi.bprintf(PRINT_HIGH,"apooX %f >= %f\n",i ,tracelimit);
//if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) gi.bprintf(PRINT_HIGH,"apoo1 %f %f \n",i,trmax[2]);
			return false;
		}

//		rs_trace = gi.trace (trstart, trmin, trmax, trend,ent, tcontents );
		*bottom = rs_trace.endpos[2] - ent->s.origin[2];

		if(!ent->client->zc.route_trace) 
		{
//gi.bprintf(PRINT_HIGH,"apoo2\n");
//if(ent->client->zc.waterstate == 1 && ryaw == ent->client->zc.moveyaw) gi.bprintf(PRINT_HIGH,"apoo2\n");
			if(rs_trace.plane.normal[2] < 0.7 && (!ent->client->zc.waterstate && ent->groundentity)) return false;
		}
		else 
		{
			Get_RouteOrigin(ent->client->zc.routeindex,v);
			if(rs_trace.plane.normal[2] < 0.7 && v[2] < ent->s.origin[2]) return false;
		}

		if( *bottom >/*=*/ tracelimit - 5)
		{
//gi.bprintf(PRINT_HIGH,"apooY %f > %f\n",*bottom ,tracelimit - 5);
//gi.bprintf(PRINT_HIGH,"apoo3\n");
//if(ent->client->zc.waterstate == 1 && ryaw == ent->client->zc.moveyaw) gi.bprintf(PRINT_HIGH,"apoo3\n");
			return false;
		}
		pos[0] = rs_trace.endpos[0];
		pos[1] = rs_trace.endpos[1];
		pos[2] = rs_trace.endpos[2];

		if(trmax[2] == 32)
		{
			if(Bot_ExploAvoid(ent,pos))
			{
				if(!CheckLaser(pos,trmax,trmin))
				return true;
			}
			return false;
		}
		
//		trmax[2] = 32;
		VectorCopy(pos,trend);
		trend[2] += 28;
		rs_trace = gi.trace (pos, trmin, trmax, trend,ent, tcontents );
		if(!rs_trace.allsolid && !rs_trace.startsolid && rs_trace.fraction == 1.0)
		{
			if(Bot_ExploAvoid(ent,pos))
			{
				if(!CheckLaser(pos,trmax,trmin))
				return true;
			}
			return false;
		}
		if(Bot_ExploAvoid(ent,pos))
		{
			if(!CheckLaser(pos,trmax,trmin))
			return 2;
		}
		return false;


/*		trmax[2] = 32;
		rs_trace = gi.trace (pos, trmin, trmax, pos,ent, tcontents );
		if(!rs_trace.allsolid && !rs_trace.startsolid)	return true;
		return 2;*/
	} 
	else								//進めたとしても落ちたくない時のためのチェック
	{
		pos[0] = trstart[0];
		pos[1] = trstart[1];
		pos[2] = trstart[2];
		VectorCopy (trstart, trend);

		trstart[2] = trend[2] -8190;
		rs_trace = gi.trace (trend, trmin, trmax, trstart,ent, tcontents | MASK_OPAQUE);

		*bottom = rs_trace.endpos[2] - ent->s.origin[2];

		if(0/*rs_trace.fraction != 1.0 && rs_trace.plane.normal[2] < 0.7 && ent->waterlevel < 2 && ent->groundentity*/)
		{
			i = Get_vec_yaw (rs_trace.plane.normal,ryaw);
			if( i < 90)
			{
				if(*bottom < 0 ) *bottom *= 3.0;
			}
			else 
			{
//if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) gi.bprintf(PRINT_HIGH,"apoo2\n");
//if(ent->client->zc.waterstate == WAS_FLOAT && ryaw == ent->client->zc.moveyaw) gi.bprintf(PRINT_HIGH,"apooX\n");
				return false;
			}
		}
		if(0/*!ent->client->zc.route_trace*/)
		{
			if(rs_trace.plane.normal[2] > 0 && rs_trace.plane.normal[2] < 0.7) *bottom /= rs_trace.plane.normal[2];
		}
/*		else
		{
			
		}*/

		contents = 0;
		if(!ent->waterlevel)
		{
			if (ent->client->enviro_framenum > level.framenum) contents = CONTENTS_LAVA;
			else contents = ( CONTENTS_LAVA | CONTENTS_SLIME);
		}
		if( rs_trace.contents & contents ) *bottom = -9999; /*return false;*/
		else if( rs_trace.surface->flags & SURF_SKY ) *bottom = -9999;		

		if(!ent->waterlevel && (ent->client->ps.pmove.pm_flags & PMF_DUCKED)
			&& ent->groundentity == NULL && ent->velocity[2] > 10 && trmax[2] == 4) return 2;


		if(trmax[2] == 32)
		{
			if(Bot_ExploAvoid(ent,pos))
			{
				if(!CheckLaser(pos,trmax,trmin))
				return true;
			}
			return false;
		}
		
//		trmax[2] = 32;
		VectorCopy(pos,trend);
		trend[2] += 28;
		rs_trace = gi.trace (pos, trmin, trmax, trend,ent, tcontents );
		if(!rs_trace.allsolid && !rs_trace.startsolid && rs_trace.fraction == 1.0)
		{
			if(Bot_ExploAvoid(ent,pos))
			{
				if(!CheckLaser(pos,trmax,trmin))
				return true;
			}
			return false;
		}
		if(Bot_ExploAvoid(ent,pos))
		{
			if(!CheckLaser(pos,trmax,trmin))
			return 2;
		}
		return false;
	}
}

int Bot_Watermove ( edict_t *ent,vec3_t pos,float dist,float upd)
{
	trace_t		rs_trace;
	vec3_t		trmin,trmax,touchmin;
	float		i,j;

	float		max,vec;

	VectorCopy(ent->s.origin,trmax);

	trmax[2] += upd;

	rs_trace = gi.trace (ent->s.origin, ent->mins, ent->maxs, trmax,ent, /*MASK_BOTSOLID*/MASK_BOTSOLIDX);

	if(!rs_trace.allsolid && !rs_trace.startsolid )
	{
		if(rs_trace.fraction > 0)
		{
			VectorCopy(rs_trace.endpos,pos);
			return true;
			if(upd < 0) ent->velocity[2] = 0;
		}
	}
//gi.bprintf(PRINT_HIGH,"Water MOVE NG %f %f!\n",dist,upd);
//	return false;
//	if(upd > -7 && upd < 7)	return false;

	VectorCopy(ent->s.origin,trmin);
	trmin[2] += upd;
	
	vec = -1;
	max = 0;
	for(i = 0;i < 360; i += 10)
	{
		if(i && upd > -13 && upd < 0/*13*/) break;
		if(i > 60 && i < 300) continue;

		j = ent->client->zc.moveyaw + i;
		
		if(j > 180) j = j - 360;
		else if(j < -180) j = j + 360;
		else j = i;

		touchmin[0] = cos(j) * 24 ;
		touchmin[1] = sin(j) * 24 ;
		touchmin[2] = 0;

		VectorAdd(trmin,touchmin,trmax);
		rs_trace = gi.trace (trmax/*ent->s.origin*/, ent->mins, ent->maxs, trmin,ent, MASK_BOTSOLIDX);

//		yaw = VectorLength(trmax); 
		if(!rs_trace.allsolid && !rs_trace.startsolid )
		{
			VectorAdd(rs_trace.endpos,touchmin,trmax);
			rs_trace = gi.trace (trmax, ent->mins, ent->maxs, trmax,ent, MASK_BOTSOLIDX);
//gi.bprintf(PRINT_HIGH,"NGAAAAAAAAAAAAAAAAAAAAAAAAAAA!\n");

//			VectorSubtract(rs_trace.endpos,ent->s.origin,trmax);
			if(!rs_trace.allsolid && !rs_trace.startsolid )
			{
//gi.bprintf(PRINT_HIGH,"go go go!\n");
				vec = i;break;
			}
		}
	}

	if(vec == -1)
	{
//gi.bprintf(PRINT_HIGH,"Water MOVE NG %f %f!\n",dist,upd);
		return false;
	}

//gi.bprintf(PRINT_HIGH,"Water MOVE OK %f %f!\n",dist,upd);
	VectorCopy(trmax,pos);
	if(upd < 0) ent->velocity[2] = 0;
	return true;
	
	touchmin[0] = cos(vec) * 16;//dist ;
	touchmin[1] = sin(vec) * 16;//dist ;
	touchmin[2] = 0;

	VectorAdd(ent->s.origin,touchmin,trmin);
	VectorCopy(trmin,trmax);
	trmax[2] += upd;
	rs_trace = gi.trace (trmin, ent->mins, ent->maxs, trmax,ent, MASK_BOTSOLIDX);	

	if(rs_trace.allsolid || rs_trace.startsolid )
	{
		return false;
	}

	VectorCopy(rs_trace.endpos,pos);
	return true;


	VectorCopy(rs_trace.plane.normal,trmin);
	trmin[2] = 0;
	VectorNormalize(trmin);
	VectorAdd(trmax,trmin,trmax);
	for(i = 1.0;i < dist;i += 1.0)
	{
		rs_trace = gi.trace (trmax, ent->mins, ent->maxs,trmax,ent, MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/);
		if(!rs_trace.allsolid && !rs_trace.startsolid)
		{
			VectorCopy(trmax,pos);
			return true;				
		}
		VectorAdd(trmax,trmin,trmax);
	}
//	gi.bprintf(PRINT_HIGH,"failed2\n");
	return false;
}

int Bot_moveW ( edict_t *ent,float ryaw,vec3_t pos,float dist,float *bottom)
{
	float		yaw;
	vec3_t		trstart,trend;
	trace_t		rs_trace;

	int			contents;

	int			tcontents;

	if (ent->client->enviro_framenum > level.framenum) contents = CONTENTS_LAVA;
	else contents = ( CONTENTS_LAVA | CONTENTS_SLIME);

	tcontents = MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/;
	tcontents |= CONTENTS_WATER;

	//移動先がどうなっているのか調べる
	yaw = ryaw*M_PI*2 / 360;
	trend[0] = cos(yaw) * dist ;				//start
	trend[1] = sin(yaw) * dist ;
	trend[2] = 0;
	VectorAdd (trend, ent->s.origin, trstart);

	pos[0] = trstart[0];
	pos[1] = trstart[1];
	pos[2] = trstart[2];
	VectorCopy (trstart, trend);

	trstart[2] = trend[2] -8190;//95;
	rs_trace = gi.trace (trend, ent->mins, ent->maxs, trstart,ent, tcontents);

	if((trend[2] - rs_trace.endpos[2]) >= 95) return false;

	if(rs_trace.contents & contents) return false;
	if(!(rs_trace.contents & CONTENTS_WATER)) return false;

	*bottom = rs_trace.endpos[2] - ent->s.origin[2];
	return true;
}

//-----------------------------------------------------------------------------------------
// Bank check
//	true	safe
//	false	danger
qboolean BankCheck(edict_t *ent,vec3_t pos)
{
	trace_t	rs_trace;
	vec3_t	end,v1,v2;

	VectorSet(v1,-16,-16,-24);
	VectorSet(v2,16,16,16);

	VectorCopy(pos,end);

	end[2] -= 5000;

	rs_trace = gi.trace (pos, v1, v2,end,ent, MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/);

	if(rs_trace.startsolid || rs_trace.allsolid) return false;
	if(rs_trace.plane.normal[2] < 0.8 ) return false;
	return true;
}


//-----------------------------------------------------------------------------------------
// hazard check
//	true	safe
//	false	danger
qboolean HazardCheck(edict_t *ent,vec3_t pos)
{
	trace_t	rs_trace;
	vec3_t	end,v1,v2;
	int		contents;

	VectorSet(v1,-16,-16,-16);
	VectorSet(v2,16,16,16);

	VectorCopy(pos,end);

	end[2] -= 8190;

	if (ent->client->enviro_framenum > level.framenum) contents = CONTENTS_LAVA;
	else contents = ( CONTENTS_LAVA | CONTENTS_SLIME);

	rs_trace = gi.trace (pos, v1, v2,end,ent, MASK_OPAQUE);

	if(rs_trace.contents & contents) return false;
	return true;
}

//-----------------------------------------------------------------------------------------
// bot's shot
/*qboolean Bot_Shot()
{


	if( ent->client->weaponstate == WEAPON_READY)
	{
		if(trent->movetype == MOVETYPE_STOP && trent->classname)
		{
			&& trent->health && trent->moveinfo.state == 1
				&& trent->takedamage)//trent->moveinfo.wait == 0)
			{
				trmax[0] = (trent->absmin[0] + trent->absmax[0]) / 2;
				trmax[1] = (trent->absmin[1] + trent->absmax[1]) / 2;
				trmax[2] = (trent->absmin[2] + trent->absmax[2]) / 2;							
				rs_trace = gi.trace (ent->s.origin, NULL, NULL, trmax ,ent, MASK_SHOT);

				if(rs_trace.ent == trent)
							{
					//		gi.bprintf(PRINT_HIGH,"kkkkkkk\n");
					//		continue;
								VectorSubtract (trmax, ent->s.origin,trmin);
								ent->client->ammo_index = 0;
								ent->client->pers.weapon = FindItem("Blaster");
								ShowGun(ent);
								ent->s.angles[YAW] = Get_yaw(trmin);
								ent->s.angles[PITCH] = Get_pitch(trmin);
								ent->client->buttons |= BUTTON_ATTACK;
								ent->client->zc.objshot = true;
							}	 
						}
					}
				}

*/
//-----------------------------------------------------------------------------------------
// set the bot's combatstate

void Set_Combatstate(edict_t *ent,int foundedenemy)
{
	vec3_t	v;
	gclient_t	*client;
	float	distance;
	edict_t	*target;
	int		enewep;
	int		combskill;
	float	aim;

	client = ent->client;

	target = client->zc.first_target;

	if(client->zc.zcstate & STS_LADDERUP) return;

	if(target == NULL)
	{
		client->zc.zccmbstt &= ~CTS_COMBS; // clear status
		return;
	}

	//target is dead
	if(!target->inuse || target->deadflag || target->solid != SOLID_BBOX)
	{
		client->zc.battleduckcnt = 0;
		client->zc.first_target = NULL;
		client->zc.zccmbstt &= ~CTS_COMBS; //clear status

		if((9 * random()) < Bot[client->zc.botindex].param[BOP_COMBATSKILL])
															UsePrimaryWeapon(ent);
		return;
	}

	if(!Bot_trace(ent,target))
	{
		if(client->zc.targetlock <= level.time)
		{
			client->zc.first_target = NULL;
			return;
		}
		client->zc.zccmbstt |= CTS_ENEM_NSEE;//can't see
//		return;
	}
	else
	{
		ent->client->zc.targetlock = level.time + FRAMETIME * 12;
		ent->client->zc.zccmbstt &= ~CTS_ENEM_NSEE;//can see
		ent->client->zc.battlemode &= ~FIRE_ESTIMATE;
	}

	VectorSubtract(target->s.origin,ent->s.origin,v);
	distance = VectorLength(v);

	//enemy's weapon
	enewep = Get_KindWeapon(target->client->pers.weapon);

	//status set
	aim = 10.0 - (float)Bot[client->zc.botindex].param[BOP_AIM];
	if(aim <= 0 || aim > 10) aim = 5; 
	combskill = (int)Bot[client->zc.botindex].param[BOP_COMBATSKILL];
	if(combskill < 0 || combskill > 9) combskill = 5;


	if(!(client->zc.zccmbstt & CTS_ENEM_NSEE)) Combat_Level0(ent,foundedenemy,enewep,aim,distance,combskill);
	else if(client->zc.zccmbstt & FIRE_REFUGE) Combat_Level0(ent,foundedenemy,enewep,aim,distance,combskill);
	else Combat_LevelX(ent,foundedenemy,enewep,aim,distance,combskill);

	if(client->zc.first_target)
	{
		client->zc.last_target = client->zc.first_target;
		VectorCopy(client->zc.first_target->s.origin,client->zc.last_pos);
	}
	return;
}

//-----------------------------------------------------------------------------------------
// Bot Jump
// return true		sequaense done
// return false		failed
qboolean Get_FlyingSpeed(float bottom,float block,float dist,float *speed)
{
	float tdist;

	if(bottom >= 40)
	{
		if(block > 4 ) return false;
		tdist = (dist * block) / 4 ;
	}
	else if(bottom >= 35)
	{
		if(block > 5) return false;
		tdist = (dist * block) / 5 ;
	}
	else if(bottom >= 30)
	{
		if(block > 6) return false;
		tdist = (dist * block) / 6 ;
	}
	else if(bottom >= 20)
	{
		if(block > 7) return false;
		tdist = (dist * block) / 7 ;
	}
	else if(bottom >= -5)
	{
		if(block > 8 ) return false;
		tdist = (dist * block) / 8 ;
	}
	else if(bottom >= -20)
	{
		if(block > 9) return false;
		tdist = (dist * block) / 7;
	}
	else if(bottom >= -35)
	{
		if(block > 10) return false;
		tdist = (dist * block) / 6 ;
	}
	else if(bottom >= -52)
	{
		if(block > 11) return false;
		tdist = (dist * block) / 5;
	}
	else if(bottom >= -75)
	{
		if(block > 12) return false;
		tdist = (dist * block) / 4;
	}
	else if(bottom >= -95)
	{
		if(block > 13) return false;
		tdist = (dist * block) / 3;
	}
	else if(bottom >= - 125)
	{
		if(block > 14) return false;
		tdist = (dist * block) / 2;
	}
	else
	{
		if(block > 15) return false;
		tdist = (dist * block) / 2;
	}

	*speed = tdist / MOVE_SPD_RUN;
	return true;
}

qboolean Bot_Jump(edict_t *ent,vec3_t pos,float dist)
{
	float	x,yaw,tdist,bottom,speed;
	vec3_t	temppos;
	zgcl_t	*zc;

	zc = &ent->client->zc;

	yaw = zc->moveyaw;

	Bot_moveT (ent,yaw,temppos,dist,&bottom);
	if(bottom > -JumpMax) return false; 

	for( x = 2 ; x <= 16; x += 1)
	{
		tdist = dist * x;
		if( Bot_moveT (ent,yaw,temppos,tdist,&bottom) == true) 
		{
			if( x == 2 && ( bottom > - JumpMax ) && bottom <= 0)
			{
				VectorCopy( pos,ent->s.origin);
				return true;
			}
			if( bottom <= JumpMax && bottom > -JumpMax)
			{
				if(Get_FlyingSpeed(bottom,x,dist,&speed))
				{
					speed *= 1.5;
					if(speed > 1.2) speed = 1.2;
					ent->moveinfo.speed = speed;
					ent->velocity[2] += VEL_BOT_JUMP;
					gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
					PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
					Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
//					ent->s.frame = FRAME_jump1-1;
//					ent->client->anim_end = FRAME_jump6;
//					ent->client->anim_priority = ANIM_JUMP;
					return true;					
				}
			}
			continue;
		}
		else return false;
	}
	return false;
}

//-----------------------------------------------------------------------------------------
// Bot Fall
// return true		sequaense done
// return false		failed
	
qboolean Bot_Fall(edict_t *ent,vec3_t pos,float dist)
{
	zgcl_t	*zc;
	float	x,l,speed,grav,vel,ypos,yori;
	vec3_t	v,vv;
	int		mf = false;
	short	mode = 0;

	zc = &ent->client->zc;

	if(zc->second_target != NULL)// && !(zc.zcstate & STS_COMBS))
	{
		mode = 1;
		ypos = zc->second_target->s.origin[2];

		//if on hazard object cause error
		if(!HazardCheck(ent,zc->second_target->s.origin))
		{
			zc->second_target = NULL;
			return false;
		}		

		yori = ent->s.origin[2];
		VectorSubtract(zc->second_target->s.origin,pos,v);

		grav = ent->gravity * sv_gravity->value * FRAMETIME; 
		if(v[2] > 0) goto JMPCHK;

		vel = ent->velocity[2];
//		grav = ent->gravity * sv_gravity->value * FRAMETIME; 
		l = 1.0;
		for(x = 1;x <= FALLCHK_LOOPMAX;++x ,l += x )
		{
			vel -= grav;// * l;
			yori += vel * FRAMETIME;
			if(ypos >= yori)
			{
				mf = true;
				break;
			}
		}
		VectorCopy(v,vv);
		vv[2] = 0;
		l = VectorLength(vv);
		speed = l / x;
		if(speed <= MOVE_SPD_RUN && mf)
		{
			ent->moveinfo.speed = speed / MOVE_SPD_RUN;
			VectorCopy(pos,ent->s.origin);
			return true;
		}
		goto JUMPCATCH;
	}
	else if(zc->route_trace)
	{
//gi.bprintf(PRINT_HIGH,"fall\n");
		mode = 2;
		Get_RouteOrigin(zc->routeindex,vv);
		ypos = vv[2];

		//if on hazard object cause error
		if(!HazardCheck(ent,vv))
		{
			if(++zc->routeindex >= CurrentIndex) zc->routeindex = 0;

//gi.bprintf(PRINT_HIGH,"OFF 1\n"); //ppx
//gi.bprintf(PRINT_HIGH,"hazard out\n");
//			zc->route_trace = false;
			return false;
		}		
		
		yori = pos[2];
		VectorSubtract(vv,pos,v);

		grav = ent->gravity * sv_gravity->value * FRAMETIME; 	
		if(v[2] >= 0/*-8*/) goto JUMPCATCH;//JMPCHK;

		vel = ent->velocity[2];
		//grav = ent->gravity * sv_gravity->value * FRAMETIME; 
		l = 1.0;
		for(x = 1;x <= FALLCHK_LOOPMAX;++x ,l += x )
		{
			vel -= grav;// * l;
			yori += vel * FRAMETIME;
			if(ypos >= yori)
			{
				mf = true;
				break;
			}
		}

		VectorCopy(v,vv);
		vv[2] = 0;
		//vel考慮の落下
		if(Route[zc->routeindex].state == GRS_ONTRAIN)
		{
			if(1/*Route[zc->routeindex].ent->trainteam == NULL*/)
			{
				vv[0] += FRAMETIME * Route[zc->routeindex].ent->velocity[0] * x;
				vv[1] += FRAMETIME * Route[zc->routeindex].ent->velocity[1] * x;
			}
		}

		l = VectorLength(vv);
		speed = l / x;
		if(speed <= MOVE_SPD_RUN && mf)
		{
//gi.bprintf(PRINT_HIGH,"fall do\n");
			ent->moveinfo.speed = speed / MOVE_SPD_RUN;
			VectorCopy(pos,ent->s.origin);
			return true;
		}
		goto JUMPCATCH;
	}
	goto JMPCHK;

JUMPCATCH:
	vel = ent->velocity[2] + VEL_BOT_JUMP;
	yori = pos[2];
//	l = 1.0;
//	VectorCopy(v,vv);
//	vv[2] = 0;
//	l = VectorLength(vv);
//gi.bprintf(PRINT_HIGH,"J fall\n");
	mf = false;
	for(x = 1;x <= FALLCHK_LOOPMAX;++x /*,l += x*/ )
	{
		vel -= grav;
		yori += vel * FRAMETIME; 

		if(vel > 0)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
//gi.bprintf(PRINT_HIGH,"pre ok\n"); 
			}
/*			else if(mf == 2)
			{ 
				if(ypos >= yori)
					if((l / x) < MOVE_SPD_RUN)
					{
						mf = true;
						break;
					}
			}*/
		}
		else if(x > 1)
		{
//gi.bprintf(PRINT_HIGH,"oops\n");
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}

			else if(mf == 2)
			{
				if(ypos >= yori)
				{
/*					if((l / (x - 1)) <= MOVE_SPD_RUN)
					{*/
//gi.bprintf(PRINT_HIGH,"Go %f\n",l / x);
						mf = true;
						break;
//					}
				}
			}
		}
	}	
	VectorCopy(v,vv);
	vv[2] = 0;
	if(mode == 2)
	{	
		//vel考慮の落下
		if(Route[zc->routeindex].state == GRS_ONTRAIN)
		{
			if(1/*Route[zc->routeindex].ent->trainteam == NULL*/)
			{
//gi.bprintf(PRINT_HIGH,"Go!\n"); //ppx
				vv[0] += FRAMETIME * Route[zc->routeindex].ent->velocity[0] * x;
				vv[1] += FRAMETIME * Route[zc->routeindex].ent->velocity[1] * x;
			}
		}	
	}
	l = VectorLength(vv);
	
	if(x > 1) l = l / (x - 1);
	if(l < MOVE_SPD_RUN && mf == true)
	{
		ent->moveinfo.speed = l / MOVE_SPD_RUN;
		VectorCopy(pos,ent->s.origin);

		ent->velocity[2] += VEL_BOT_JUMP;
		gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
		PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
		Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
//		ent->s.frame = FRAME_jump1-1;
//		ent->client->anim_end = FRAME_jump6;
//		ent->client->anim_priority = ANIM_JUMP;
//gi.bprintf(PRINT_HIGH,"j fall do\n");
		return true;							
	}	

	if(mode == 1) goto JMPCHK;//zc->second_target = NULL;
//ponko	else zc->route_trace = false;
//gi.bprintf(PRINT_HIGH,"j fall false\n");
//	return false;
JMPCHK:
//gi.bprintf(PRINT_HIGH,"NJ \n");
	if(Bot_Jump(ent,pos,dist)) return true;

//gi.bprintf(PRINT_HIGH,"NJ FAIL\n");
	zc->second_target = NULL;
	return false;
}
//-----------------------------------------------------------------------------------------
// target jump

qboolean TargetJump(edict_t *ent,vec3_t tpos)
{
	zgcl_t	*zc;
	float	x,l,grav,vel,ypos,yori;
	vec3_t	v,vv;
	int		mf = false;

	zc = &ent->client->zc;
	grav = ent->gravity * sv_gravity->value * FRAMETIME; 

	vel = ent->velocity[2] + VEL_BOT_JUMP;
	yori = ent->s.origin[2];
	ypos = tpos[2];

	//if on hazard object cause error
	if(!HazardCheck(ent,tpos))	return false;

	VectorSubtract(tpos,ent->s.origin,v);

	for(x = 1;x <= FALLCHK_LOOPMAX * 2 ;++x )
	{
		vel -= grav;
		yori += vel * FRAMETIME; 

		if(vel > 0)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}
		}
		else if(x > 1)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}

			else if(mf == 2)
			{
				if(ypos >= yori)
				{
						mf = true;
						break;
				}
			}
		}
	}	
	VectorCopy(v,vv);
	vv[2] = 0;

	l = VectorLength(vv);
	
	if(x > 1) l = l / (x - 1);
	if(l < MOVE_SPD_RUN && mf == true)
	{
		ent->moveinfo.speed = l / MOVE_SPD_RUN;

		ent->velocity[2] += VEL_BOT_JUMP;
		gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
		PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
		Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
		return true;							
	}
	return false;
}

qboolean TargetJump_Turbo(edict_t *ent,vec3_t tpos)
{
	zgcl_t	*zc;
	float	x,l,grav,vel,ypos,yori;
	vec3_t	v,vv;
	int		mf = false;
	float	jvel;

	zc = &ent->client->zc;
	grav = ent->gravity * sv_gravity->value * FRAMETIME; 

	vel = ent->velocity[2] + VEL_BOT_JUMP;

//if(vel > (VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME ))
//	vel = VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME;
	jvel = vel;

	yori = ent->s.origin[2];
	ypos = tpos[2];

	//if on hazard object cause error
	if(!HazardCheck(ent,tpos))	return false;

	VectorSubtract(tpos,ent->s.origin,v);

	for(x = 1;x <= FALLCHK_LOOPMAX * 2 ;++x )
	{
		vel -= grav;
		yori += vel * FRAMETIME; 

		if(vel > 0)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}
		}
		else if(x > 1)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}

			else if(mf == 2)
			{
				if(ypos >= yori)
				{
						mf = true;
						break;
				}
			}
		}
	}	
	VectorCopy(v,vv);
	vv[2] = 0;

	l = VectorLength(vv);
	
	if(x > 1) l = l / (x - 1);
	if(l < MOVE_SPD_RUN && mf == true)
	{
		ent->moveinfo.speed = l / MOVE_SPD_RUN;
//		VectorCopy(pos,ent->s.origin);

		ent->velocity[2] = jvel;//VEL_BOT_JUMP;
		gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
		PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
		Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
//		ent->s.frame = FRAME_jump1-1;
//		ent->client->anim_end = FRAME_jump6;
//		ent->client->anim_priority = ANIM_JUMP;
		return true;							
	}
	return false;
}
qboolean TargetJump_Chk(edict_t *ent,vec3_t tpos,float defvel)
{
	zgcl_t	*zc;
	float	x,l,grav,vel,ypos,yori;
	vec3_t	v,vv;
	int		mf = false;

	zc = &ent->client->zc;
	grav = ent->gravity * sv_gravity->value * FRAMETIME; 

	vel = defvel + VEL_BOT_JUMP;
	yori = ent->s.origin[2];
	ypos = tpos[2];

	//if on hazard object cause error
	if(!HazardCheck(ent,tpos))	return false;

	VectorSubtract(tpos,ent->s.origin,v);

	for(x = 1;x <= FALLCHK_LOOPMAX * 2 ;++x )
	{
		vel -= grav;
		yori += vel * FRAMETIME; 

		if(vel > 0)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}
		}
		else if(x > 1)
		{
			if(mf == false)
			{
				if(ypos < yori) mf = 2;
			}

			else if(mf == 2)
			{
				if(ypos >= yori)
				{
						mf = true;
						break;
				}
			}
		}
	}	
	VectorCopy(v,vv);
	vv[2] = 0;

	l = VectorLength(vv);
	
	if(x > 1) l = l / (x - 1);
	if(l < MOVE_SPD_RUN && mf == true)
	{
		return true;							
	}
	return false;
}
//-----------------------------------------------------------------------------------------
// set anim
void Set_BotAnim(edict_t *ent,int anim,int frame,int end)
{
	if(ent->client->anim_priority < anim)
	{
		ent->s.frame = frame;
		ent->client->anim_end = end;
	}
}


//-----------------------------------------------------------------------------------------
// Get Water State
void Get_WaterState(edict_t *ent)
{
	zgcl_t	*zc;
	vec3_t	trmin,trmax;
	float	x;
	trace_t		rs_trace;

	zc = &ent->client->zc;

	//---------------
	//get waterstate
	if(ent->waterlevel)
	{
		VectorCopy(ent->s.origin,trmax);
		VectorCopy(ent->s.origin,trmin);
		trmax[2] -= 24;
		trmin[2] += 8;

		rs_trace = gi.trace (trmin, NULL,NULL,trmax,ent, MASK_WATER );
		x = trmin[2] - rs_trace.endpos[2];

		if(rs_trace.allsolid || rs_trace.startsolid || (/*x >= 4 &&*/ x < 4.0 )) zc->waterstate = WAS_IN;
		else 
		{

			if(x >= 4.0 && x <= 12.0 ) zc->waterstate = WAS_FLOAT; 
			else zc->waterstate = WAS_NONE;
		}
	}
	else zc->waterstate = WAS_NONE;
}


//-----------------------------------------------------------------------------------------
// Get origin of Route Index
void Get_RouteOrigin(int index,vec3_t pos)
{
	edict_t	*e;

	//when normal or items
	if(Route[index].state <= GRS_ITEMS || Route[index].state >= GRS_GRAPSHOT)
	{
		if(Route[index].state == GRS_ITEMS)
		{
			VectorCopy(Route[index].ent->s.origin,pos);
			pos[2] += 8;
		}
		else VectorCopy(Route[index].Pt,pos);

	}
	//when plat
	else if(Route[index].state == GRS_ONPLAT)
	{
		VectorCopy(Route[index].ent->union_ent->s.origin,pos);
		pos[2] += 8;
	}
	//when train
	else if(Route[index].state == GRS_ONTRAIN)
	{
		if(Route[index].ent->trainteam == NULL)
		{
			VectorCopy(Route[index].ent->union_ent->s.origin,pos);
			pos[2] += 8;
			return;
		}
		if(Route[index].ent->target_ent)
		{
			if(VectorCompare(Route[index].Tcourner,Route[index].ent->target_ent->s.origin))
			{
				VectorCopy(Route[index].ent->union_ent->s.origin,pos);
				pos[2] += 8;
				return;
			}
		}
		e = Route[index].ent->trainteam;
		while(1)
		{
			if(e == Route[index].ent) break;
			if(e->target_ent)
			{
				if(VectorCompare(Route[index].Tcourner,e->target_ent->s.origin))
				{
					VectorCopy(e->union_ent->s.origin,pos);
					pos[2] += 8;
					Route[index].ent = e;
					return;
				}
			}
			e = e->trainteam;
		}
		VectorCopy(Route[index].ent->union_ent->s.origin,pos);
		pos[2] += 8;
		return;
	}
	else if(Route[index].state == GRS_ONDOOR)
	{
		if(Route[index].ent->union_ent)
		{
			VectorCopy(Route[index].ent->union_ent->s.origin,pos);
			pos[2] += 8;
		}
		else if(index + 1 < CurrentIndex)
		{
			if(Route[index + 1].state <= GRS_ITEMS )
			{
				VectorCopy(Route[index + 1].Pt,pos);
				if(Route[index + 1].state == GRS_ITEMS) pos[2] += 8;
				pos[2] += 8;
			}
			//when plat or train
			else if(Route[index + 1].state <= GRS_ONTRAIN)
			{
				VectorCopy(Route[index + 1].ent->union_ent->s.origin,pos);
				pos[2] += 8;
			}
			else if(Route[index + 1].state == GRS_PUSHBUTTON)
			{
				VectorCopy(Route[index + 1].ent->union_ent->s.origin,pos);
				pos[2] += 8;
			}
			else VectorCopy(Route[index + 1].Pt,pos);
		}
		else
		{
			pos[0] = (Route[index].ent->absmin[0] + Route[index].ent->absmax[0]) / 2;
			pos[1] = (Route[index].ent->absmin[1] + Route[index].ent->absmax[1]) / 2;
			pos[2] = Route[index].ent->absmax[2];			
		}
	}
	else if(Route[index].state == GRS_PUSHBUTTON) VectorCopy(Route[index].ent->union_ent->s.origin,pos);
}

//-----------------------------------------------------------------------------------------
// search nearly pod
void Search_NearlyPod(edict_t *ent)
{
	vec3_t	v,v1,v2;
	float x;

	if(Route[ent->client->zc.routeindex].state >= GRS_ITEMS)	return;
//	else if(Route[ent->client->zc.routeindex].state ==/*>=*/ GRS_ITEMS)
//	{
//		if(Route[ent->client->zc.routeindex].ent->solid != SOLID_TRIGGER) return;
//	}

	if((ent->client->zc.routeindex + 1) < CurrentIndex)
	{
		if(Route[ent->client->zc.routeindex + 1].state >= GRS_ITEMS)	return;
		Get_RouteOrigin(ent->client->zc.routeindex + 1,v);
		if(TraceX(ent,v))
		{
			VectorSubtract(v,ent->s.origin,v1);

			Get_RouteOrigin(ent->client->zc.routeindex,v);
			VectorSubtract(v,ent->s.origin,v2);
			x = fabs(v1[2]);

			if(VectorLength(v1) < VectorLength(v2) && x <= JumpMax 
				&& Route[ent->client->zc.routeindex].state <= GRS_ONROTATE)
			{
				ent->client->zc.routeindex++;
			}
			else if(ent->client->zc.waterstate) return;
			else if(v2[2] > JumpMax && fabs(v1[2]) < JumpMax) ent->client->zc.routeindex++;

		}
	}
}

int Get_KindWeapon(gitem_t	*it)
{
	if(it == NULL) return WEAP_BLASTER;

	if(it->weaponthink		== Weapon_Shotgun)		return WEAP_SHOTGUN;
	else if(it->weaponthink == Weapon_SuperShotgun) return WEAP_SUPERSHOTGUN;
	else if(it->weaponthink == Weapon_Machinegun)	return WEAP_MACHINEGUN;
	else if(it->weaponthink == Weapon_Chaingun)		return WEAP_CHAINGUN;
	else if(it->weaponthink == Weapon_Grenade)		return WEAP_GRENADES;
	else if(it->weaponthink == Weapon_Trap)			return WEAP_TRAP;
	else if(it->weaponthink == Weapon_GrenadeLauncher)	return WEAP_GRENADELAUNCHER;
	else if(it->weaponthink == Weapon_RocketLauncher)	return WEAP_ROCKETLAUNCHER;
	else if(it->weaponthink == Weapon_HyperBlaster) return WEAP_HYPERBLASTER;
	else if(it->weaponthink == Weapon_Ionripper)	return WEAP_BOOMER;
	else if(it->weaponthink == Weapon_Railgun)		return WEAP_RAILGUN;
	else if(it->weaponthink == Weapon_Phalanx)		return WEAP_PHALANX;
	else if(it->weaponthink == Weapon_BFG)			return WEAP_BFG;
	else if(it->weaponthink == CTFWeapon_Grapple)	return WEAP_GRAPPLE;
	else return WEAP_BLASTER;
}

//-----------------------------------------------------------------------------------------
//
//
//
// normal bot's AI
//
//
//
//-----------------------------------------------------------------------------------------

void Bots_Move_NORM (edict_t *ent)
{
	float		dist;		//moving distance
	zgcl_t		*zc;		//zc's address
	
	int			foundedenemy;

	gitem_t		*item;

	float		x,yaw,iyaw,f1,f2,f3,bottom;
	qboolean	tempflag;//,buttonuse;
	vec3_t		temppos;

	trace_t		rs_trace;
	edict_t		*touch[MAX_EDICTS],*trent;
	vec3_t		touchmin,touchmax,v,vv;
	vec3_t		trmin,trmax;
	int			i,j,k;
	qboolean	canrocj,waterjumped;
	edict_t		*it_ent;
	gitem_t		*it;

	edict_t		*front,*left,*right,*e;

	char		*string;

	cplane_t	plane;

	vec3_t		Origin,Velocity;//original param
	float		OYaw;			//

	qboolean	ladderdrop;		


	trace_priority = TRP_NORMAL;	//trace on

	zc = &ent->client->zc;		//client add

	ent->client->zc.objshot = false;		//object shot clear

	ent->client->buttons &= ~BUTTON_ATTACK;

	//--------------------------------------------------------------------------------------
	//Solid Check
	i = gi.pointcontents (ent->s.origin);
	if(i & CONTENTS_SOLID)
	T_Damage (ent, ent, ent, ent->s.origin, ent->s.origin, ent->s.origin,100 , 1, 0, MOD_CRUSH);

	
	if(VectorCompare(ent->s.origin,ent->s.old_origin))
	{
		if(ent->groundentity == NULL && !ent->waterlevel) 
		{
			VectorCopy(ent->s.origin,v);
			v[2] -= 1.0;
			rs_trace = gi.trace(ent->s.origin,ent->mins,ent->maxs,v,ent,MASK_BOTSOLIDX);		
			if(!rs_trace.allsolid && !rs_trace.startsolid) ent->groundentity = rs_trace.ent;
		}
	}
	//	VectorCopy(ent->s.origin,Origin);
//	VectorCopy(ent->velocity,Velocity);
//	OYaw = ent->s.angles[YAW];

	//--------------------------------------------------------------------------------------
	//Check Debug mode
	if(chedit->value)
	{
		j = false;
		if(!zc->route_trace )
		{
//gi.bprintf(PRINT_HIGH,"route off\n");
			j = true;
		}
		if(zc->routeindex >= CurrentIndex)
		{
//gi.bprintf(PRINT_HIGH,"index overflow\n");
			j = true;
		}
		else if(Route[zc->routeindex].index == 0 && zc->routeindex > 0)
		{
//gi.bprintf(PRINT_HIGH,"index end\n");
			j = true;
		}

		if(j)
		{
			RemoveBot();
			//gi.cprintf(NULL,PRINT_HIGH,"Tracing failed.\n");
			return;
		}
	}
	//--------------------------------------------------------------------------------------
	//get JumpMax
	if(JumpMax == 0)
	{
		x = /*ent->velocity[2] + */ VEL_BOT_JUMP - ent->gravity * sv_gravity->value * FRAMETIME;
		JumpMax = 0;
		while(1)
		{
			JumpMax += x * FRAMETIME; 
			x -= ent->gravity * sv_gravity->value * FRAMETIME;
			if( x < 0 ) break;
		}
//gi.bprintf(PRINT_HIGH,"JumpMax %f",JumpMax);
	}
/*	if(!JmpTableChk)
	{
		
	
	}*/
	//--------------------------------------------------------------------------------------
	//target set
	if(!zc->havetarget && zc->route_trace)
	{
		k = 0;
		//primary weapon
		j = mpindex[Bot[zc->botindex].param[BOP_PRIWEP]];
		//secondary weapon
//		if(j && ent->client->pers.inventory[j]) j = mpindex[Bot[zc->botindex].param[BOP_SECWEP]];

		//ctf
		if(0/*ctf->value && bot_team_flag1 && bot_team_flag2*/)
		{
			it = NULL;
			if(ent->client->resp.ctf_team == CTF_TEAM1) 
			{
				if(zc->ctfstate == CTFS_DEFENDER || zc->ctfstate == CTFS_CARRIER) it = bot_team_flag1->item;
				else if(zc->ctfstate == CTFS_OFFENCER) it = bot_team_flag2->item;
			}
			else if(ent->client->resp.ctf_team == CTF_TEAM2) 
			{
				if(zc->ctfstate == CTFS_DEFENDER || zc->ctfstate == CTFS_CARRIER) it = bot_team_flag2->item;	
				else if(zc->ctfstate == CTFS_OFFENCER) it = bot_team_flag1->item;
			}
			if(it) {k = true;}
		}
if(ctf->value) j = 0;
		if((j && !ent->client->pers.inventory[j]) || k)
		{
			if(!k) it = &itemlist[j];
			if(zc->targetindex < zc->routeindex
				|| zc->targetindex >= CurrentIndex) zc->targetindex = zc->routeindex;
			for(i = zc->targetindex + 1;i < (zc->targetindex + 50);i++)
			{
				if(i > CurrentIndex) break;
				if(Route[i].state == GRS_ITEMS)
				{
					if(Route[i].ent->item == it)
					{
//gi.bprintf(PRINT_HIGH,"Target Flag On\n");
						zc->havetarget = true;
						break;
					}
					else if(!ctf->value && Route[i].ent->solid == SOLID_TRIGGER)
					{
						//Quad
						if(j = mpindex[MPI_QUAD])
							if(Route[i].ent->item == &itemlist[j])
							{zc->havetarget = true;	break;}
						//Quad fire
						if(j = mpindex[MPI_QUADF])
							if(Route[i].ent->item == &itemlist[j])
							{zc->havetarget = true;	break;}
						//Quad fire
						if(j = mpindex[MPI_PENTA])
							if(Route[i].ent->item == &itemlist[j])
							{zc->havetarget = true;	break;}
					}
				}
			}
			zc->targetindex = i;
		}
		else
		{
			//quad
			j = mpindex[MPI_QUAD];
			//quad fire
			if(!j) j = mpindex[MPI_QUADF];

			if(j)
			{
				it = &itemlist[j];
				if(zc->targetindex < zc->routeindex
					|| zc->targetindex >= CurrentIndex) zc->targetindex = zc->routeindex;
				for(i = zc->targetindex + 1;i < (zc->targetindex + 25);i++)
				{
					if(i > CurrentIndex) break;
					if(Route[i].state == GRS_ITEMS)
					{
						if(Route[i].ent->item == it)
						{
							if(Route[i].ent->solid == SOLID_TRIGGER)
							{
								zc->havetarget = true;
								break;
							}
						}
					}
				}
				zc->targetindex = i;
			}
		}
	}
	else if(zc->havetarget)
	{
		if(zc->targetindex < zc->routeindex)
		{
			zc->havetarget = false;
			zc->targetindex = zc->routeindex;
		}

		else if(ctf->value) 
		{
			it = NULL;
			if(ent->client->resp.ctf_team == CTF_TEAM1) 
			{
				if(zc->ctfstate == CTFS_DEFENDER || zc->ctfstate == CTFS_CARRIER) it = bot_team_flag1->item;	
				else if(zc->ctfstate == CTFS_OFFENCER) it = bot_team_flag2->item;
			}
			else if(ent->client->resp.ctf_team == CTF_TEAM2) 
			{
				if(zc->ctfstate == CTFS_DEFENDER || zc->ctfstate == CTFS_CARRIER) it = bot_team_flag2->item;	
				else if(zc->ctfstate == CTFS_OFFENCER) it = bot_team_flag1->item;
			}
			if(Route[zc->targetindex].ent->item != it)
			{
				zc->havetarget = false;
				zc->targetindex = zc->routeindex;
			}
		}
	}
	//--------------------------------------------------------------------------------------
	//can rocket jump?
	it = Fdi_ROCKETLAUNCHER;//FindItem("Rocket Launcher");
	i = ITEM_INDEX(Fdi_ROCKETS/*FindItem("Rockets")*/);

	if(	ent->client->pers.inventory[ITEM_INDEX(it)]
		&& ent->client->pers.inventory[i] > 0) canrocj = true;
	else canrocj = false;
	if(!Bot[zc->botindex].param[BOP_ROCJ]) canrocj = false;

	//--------------------------------------------------------------------------------------
	//ducking check
	if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
	{
		if(ent->client->zc.battleduckcnt > 0 && ent->groundentity) goto DCHCANC;

		VectorSet(v,16,16,32);
		VectorCopy(ent->s.origin,v);

		v[2] += 28;

		rs_trace = gi.trace(ent->s.origin,ent->mins,ent->maxs,v,ent,MASK_BOTSOLIDX);
//gi.bprintf(PRINT_HIGH,"try to duck clear!\n");
		if(!rs_trace.startsolid && !rs_trace.allsolid && rs_trace.fraction == 1.0)
		{
//gi.bprintf(PRINT_HIGH,"duck cleared!\n");
			ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
			ent->maxs[2] = 32;
		}
//		else gi.bprintf(PRINT_HIGH,"failed %i %i\n",rs_trace.startsolid ,rs_trace.allsolid);
	}
	else if(ent->velocity[2] > 10 && ent->groundentity == NULL
		&& !(zc->zcstate & STS_SJMASK))
	{
		VectorSet(v,16,16,40);
		rs_trace = gi.trace(ent->s.origin,ent->mins,v,ent->s.origin,ent,MASK_BOTSOLIDX);

		if(rs_trace.startsolid || rs_trace.allsolid)
		{
			ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
			ent->maxs[2] = 4;
		}	
	}
DCHCANC://しゃがみっぱなし	
	//--------------------------------------------------------------------------------------
	//movingspeed set
	if(ent->groundentity || ent->waterlevel)
	{
		if(ent->waterlevel) 
		{
			if(!(zc->zcstate & STS_WATERJ)) zc->zcstate &= ~STS_SJMASK;
		}
		else zc->zcstate &= ~STS_SJMASK;
		if(ent->groundentity && !ent->waterlevel) ent->moveinfo.speed = 1.0;
		else if(ent->waterlevel && ent->velocity[2] <= 1) ent->moveinfo.speed = 1.0;
	}

	// if ducking down to da speed
	if(ent->client->ps.pmove.pm_flags & PMF_DUCKED && ent->groundentity) dist = MOVE_SPD_DUCK * ent->moveinfo.speed;
	else
	{
		if( !ent->waterlevel )
		{
			if(chedit->value || !Bot[zc->botindex].param[BOP_WALK] || !ent->groundentity) dist = MOVE_SPD_RUN * ent->moveinfo.speed;
			else dist = MOVE_SPD_WALK * ent->moveinfo.speed;
		}
		else 
		{
			if(ent->groundentity && ent->waterlevel < 2 ) dist = MOVE_SPD_RUN * ent->moveinfo.speed;
			else dist = MOVE_SPD_WATER * ent->moveinfo.speed; 
		}
		if(ent->groundentity) dist *= zc->ground_slope;
	}

	//--------------------------------------------------------------------------------------
	//get waterstate
	Get_WaterState( ent );

	//--------------------------------------------------------------------------------------
	//
	//search for enemy
	//
//	foundedenemy = 0;
//	i = CTS_AIMING ;

	zc->firstinterval += 2;
	if(zc->firstinterval >= 10)
	{
		zc->foundedenemy = Bot_SearchEnemy(ent);
		zc->firstinterval = Bot[zc->botindex].param[BOP_REACTION];
		if(zc->firstinterval > 10) zc->firstinterval = 10;
		if(zc->firstinterval < 0) zc->firstinterval = 0;
	}
	//--------------------------------------------------------------------------------------
	//
	//bot's combat status set
	//
	foundedenemy = zc->foundedenemy;
//	if(ent->client->ctf_grapple && !(ent->client->buttons & BUTTON_ATTACK)) {}
//	else
	Set_Combatstate(ent,foundedenemy);
	if(trace_priority == TRP_ALLKEEP) goto VCHCANSEL;
	//--------------------------------------------------------------------------------------
	//brause target status
	if(zc->second_target != NULL && zc->route_trace) 
								zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
	if(zc->second_target != NULL && !(zc->zcstate & STS_WAITSMASK))
	{
		if(zc->second_target->solid != SOLID_TRIGGER || !zc->second_target->inuse)
		{
			zc->second_target = NULL;
		}
		else if(!Bot_trace (ent,zc->second_target))
		{
			zc->second_target = NULL;
		}
		else if((zc->second_target->s.origin[2] - ent->s.origin[2]) > 32 && zc->waterstate != WAS_IN)
		{
			VectorSubtract(zc->second_target->s.origin,ent->s.origin,temppos);
			x = zc->second_target->moveinfo.start_origin[2] - ent->s.origin[2];
			k = false;
			if(temppos[2] > 32)
			{
				if(!canrocj)
				{
					if(x < 0 || x > 32) k = true;
					else if(!Bot_trace2 (ent,zc->second_target->moveinfo.start_origin)) k = true;
				}
				else
				{
					if(temppos[2] > 300) k = true;
				}
			}
			else
			{
				if(temppos[0] <= (ent->absmax[0] + 32) && temppos[0] >= (ent->absmin[0] + 32))
				if(temppos[1] <= (ent->absmax[1] + 32) && temppos[1] >= (ent->absmin[1] + 32))
				if(temppos[2] <= (ent->absmax[2] + 32) && temppos[2] >= (ent->absmin[2] + 32))
						k = true;
			}
			if(k)
			{
				zc->second_target = NULL;
//				if(zc->route_trace) Search_NearlyPod(ent);
			}
		}
	}
//	if(zc->route_trace && (zc->zcstate & STS_LADDERUP)) zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
	if(zc->route_trace)
	{
//PON-CTF>>
		if(zc->routeindex > 0)
		{
			if(ent->client->ctf_grapple)
			{
				ent->client->buttons |= BUTTON_ATTACK;
			}

//			if(Route[zc->routeindex].state == GRS_GRAPSHOT)
//			{ 
//				if(Route[zc->routeindex - 1].state == GRS_GRAPRELEASE) zc->routeindex++;
//			}
			if(!zc->first_target && ent->client->pers.weapon != Fdi_GRAPPLE	)
			{
				for(i = 0;i < (5 * 2);i++)
				{
					if((zc->routeindex + i) >= CurrentIndex) break;
					if(Route[zc->routeindex + i].state == GRS_GRAPSHOT)
					{
						item = Fdi_GRAPPLE;//FindItem("Grapple");
						if(	ent->client->pers.inventory[ITEM_INDEX(item)]) item->use(ent,item);
					}
				}
			}
			//撃てGrapple
			else if(Route[zc->routeindex - 1].state == GRS_GRAPSHOT
				&& ent->client->ctf_grapple == NULL
				&& zc->first_target == NULL)
			{
				item = Fdi_GRAPPLE;;//FindItem("Grapple");

				if(	ent->client->pers.inventory[ITEM_INDEX(item)])
				{
					item->use(ent,item);
//					ent->client->ctf_grapplestate = CTF_GRAPPLE_STATE_FLY;
//					ent->client->pers.weapon = item;
//					ent->client->weaponstate = WEAPON_READY;
//					ent->s.sound = 0;
					ShowGun(ent);
					if(ent->client->weaponstate == WEAPON_READY && ent->client->pers.weapon == item)
					{
						vv[0] = ent->s.origin[0];
						vv[1] = ent->s.origin[1];
						vv[2] = ent->s.origin[2] + ent->viewheight-8+2;
//						VectorCopy(Route[zc->routeindex - 1].Pt,ent->s.origin);
						VectorSubtract(Route[zc->routeindex - 1].Tcourner,vv,v);
						ent->s.angles[YAW] = Get_yaw(v);
						ent->s.angles[PITCH] = Get_pitch(v);
						trace_priority = TRP_ANGLEKEEP;
//						item->use(ent,item);
//						if(ent->client->weaponstate == WEAPON_READY)
//						{
							ent->client->buttons |= BUTTON_ATTACK;
//						}
					}
					else
					{
						if(zc->first_target == NULL && ent->groundentity) trace_priority = TRP_ALLKEEP;
						zc->routeindex--;/* trace_priority = TRP_ALLKEEP;*/
					}
				}
			}
			else if(ent->client->ctf_grapple)
			{
				//sticking check
				if(zc->nextcheck < (level.time + FRAMETIME * 10))
				{
					VectorSubtract(zc->pold_origin,ent->s.origin,temppos);
					if(VectorLength(temppos) < 64)
					{
						if(zc->route_trace)
						{
							zc->route_trace = false;
							zc->routeindex++;
							ent->client->buttons &= ~BUTTON_ATTACK;
						}
					}

					if(zc->nextcheck < level.time) 
					{
						VectorCopy(ent->s.origin,zc->pold_origin);
						zc->nextcheck = level.time + FRAMETIME * 40;
					}
				}
				if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
				{
					if(ent->groundentity == NULL) zc->zcstate |= STS_ROCJ;

					if(Route[zc->routeindex].state != GRS_GRAPRELEASE)
					{
						for(i = 0;(zc->routeindex - i) > 0;i++)
						{
							if(Route[zc->routeindex - i].state == GRS_GRAPSHOT) break;
						}
						if((zc->routeindex - i) > 0)
						{
							for(j = 0;(zc->routeindex - i + j) < CurrentIndex;j++)
							{
								if(Route[zc->routeindex - i + j].state == GRS_GRAPRELEASE) break;
							}
							if((zc->routeindex - i + j) < CurrentIndex)
									zc->routeindex = zc->routeindex - i + j;  
						}
					}
					if(Route[zc->routeindex].state != GRS_GRAPRELEASE)
					{
						item = Fdi_GRAPPLE;//FindItem("Grapple");
					item->use(ent,item);
//						ent->client->pers.weapon = item;
//						ent->s.sound = 0;
//						ShowGun(ent);
						ent->client->buttons &= ~BUTTON_ATTACK;
					}
				}
				else if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_HANG
					&& Route[zc->routeindex].state != GRS_GRAPRELEASE)
				{
					item = Fdi_GRAPPLE;//FindItem("Grapple");
					item->use(ent,item);
//					ent->client->pers.weapon = item;
//					ent->s.sound = 0;
//					ShowGun(ent);
					ent->client->buttons &= ~BUTTON_ATTACK;
//gi.bprintf(PRINT_HIGH,"Groff 2!\n");
				}
			}

			else if(Route[zc->routeindex - 1].state == GRS_GRAPHOOK
				&& ent->client->ctf_grapple)
			{
				if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_FLY)
					trace_priority = TRP_ALLKEEP;

			}
/*			if(Route[zc->routeindex].state == GRS_GRAPHOOK
				&& ent->client->ctf_grapple)
			{
				trace_priority = TRP_ALLKEEP;
			}*/
			if(Route[zc->routeindex].state == GRS_GRAPRELEASE
				&& ent->client->ctf_grapple) 
			{
				k = 0;
				if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_FLY)
					trace_priority = TRP_ALLKEEP;
				else if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
				{
					if(1)
					{
						e = (edict_t*)ent->client->ctf_grapple;
						VectorSubtract(ent->s.origin,e->s.origin,v);
						yaw = VectorLength(v);
						if(yaw <= (Route[zc->routeindex].Tcourner[0] /*+ 32*/))
						{
//							if(yaw < 40) ent->moveinfo.speed = 0;
							item = Fdi_GRAPPLE;//FindItem("Grapple");
							item->use(ent,item);
							ent->client->buttons &= ~BUTTON_ATTACK;
							zc->routeindex++;
							k = true;
//gi.bprintf(PRINT_HIGH,"Groff 1!\n");
						}
						else if(!ent->waterlevel) trace_priority = TRP_ALLKEEP;
					}
//					gi.bprintf(PRINT_HIGH,"length %f < %f\n",Route[zc->routeindex].Tcourner[0],VectorLength(v));
				}
				else if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_HANG)
				{
/*					if((zc->routeindex + 1) < CurrentIndex)
					{
						if(Route[zc->routeindex + 1].state == GRS_GRAPSHOT)
						{
							if(TraceX(ent,Route[zc->routeindex + 1].Tcourner)) k = true; 
						}
						else k = true;
					}*/
					ent->moveinfo.speed = 0;
					k = true;
					if(k)
					{
						item = Fdi_GRAPPLE;//FindItem("Grapple");
						item->use(ent,item);
						ent->client->buttons &= ~BUTTON_ATTACK;
						zc->routeindex++;
//gi.bprintf(PRINT_HIGH,"Groff 0!\n");
					}
				}
				if(k)
				{
					if(zc->routeindex < CurrentIndex)
					{
						if(Route[zc->routeindex].state == GRS_GRAPSHOT)
						{
							if(1/*TraceX(ent,Route[zc->routeindex + 1].Tcourner)*/) zc->routeindex++;
						}
					}
				}
			}
/*			else if(ent->client->ctf_grapple)
			{
				if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL
					&& Route[zc->routeindex - 1].state == GRS_GRAPRELEASE)
				{
					ent->client->buttons &= ~BUTTON_ATTACK;
					CTFResetGrapple(ent->client->ctf_grapple);				
				}
			}*/
		}
//>>PON-CTF
//		if(trace_priority == TRP_ALLKEEP) goto VCHCANSEL;

		if(Route[zc->routeindex].state >= GRS_NORMAL) Search_NearlyPod(ent);

		Get_RouteOrigin(zc->routeindex,v);

		x = v[2] - ent->s.origin[2];

		if(zc->zcstate & STS_WAITSMASK) zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
		else if(Route[zc->routeindex].state <= GRS_ITEMS && (x > JumpMax && !zc->waterstate)
			&& !(zc->zcstate & STS_LADDERUP))
		{
			if(zc->rt_locktime <= level.time)
			{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 2\n"); //ppx
#endif
				zc->route_trace = false;
				zc->rt_releasetime = level.time + FRAMETIME * POD_RELEFRAME;
			}
		}
		else if(!TraceX(ent,v) /*&& ent->client->ctf_grapple == NULL*/)
		{	
			k = false;
			if(ent->groundentity)
			{
				if(ent->groundentity->classname[0] == 'f')
				{
					if(/*!Q_stricmp(ent->groundentity->classname, "func_plat")
						||*/ !Q_stricmp(ent->groundentity->classname, "func_train"))
					{
						zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
						k = true;
					}
				}
			}
//			if(Route[zc->routeindex].state == GRS_ONTRAIN 
//				&& /*Route[zc->routeindex].ent->trainteam*/) zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
//PON
			if(ent->client->ctf_grapple) 
			{
				if(!VectorCompare(ent->s.origin,ent->s.old_origin)) zc->rt_locktime += FRAMETIME;
			}
//PON
			if(zc->rt_locktime <= level.time && !k)
			{
//				gi.bprintf(PRINT_HIGH,"shit1");
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 3\n"); //ppx
#endif
				zc->route_trace = false;
				zc->rt_releasetime = level.time + FRAMETIME * POD_RELEFRAME;
			}
		}
		else
		{
			if(Route[zc->routeindex].state > GRS_ITEMS 
				&& Route[zc->routeindex].state <= GRS_ONPLAT)
			{
				if(0/*Route[zc->routeindex].state == GRS_ONPLAT && Route[zc->routeindex].ent->moveinfo.state != PSTATE_BOTTOM*/)
				{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 4\n"); //ppx
#endif
					zc->route_trace = false;
					zc->rt_releasetime = level.time + FRAMETIME * POD_RELEFRAME;
				}
				else if(0/*Route[zc->routeindex].ent->union_ent->solid != SOLID_TRIGGER*/)
				{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 5\n"); //ppx
#endif
					zc->route_trace = false;
					zc->rt_releasetime = level.time + FRAMETIME * POD_RELEFRAME;
				}
				else zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
			}
			else zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
		}
	}
	else
	{
		if(ent->client->ctf_grapple)
		{
			item = FindItem("Grapple");
			ent->client->pers.weapon = item;
			ent->s.sound = 0;
			ShowGun(ent);
			ent->client->buttons &= ~BUTTON_ATTACK;		
		}
	}
	if(trace_priority == TRP_ALLKEEP)
	{
		if(ent->client->ctf_grapple)
		{
			rs_trace = gi.trace (ent->s.origin, ent->maxs, ent->mins, ent->s.origin,ent, MASK_BOTSOLIDX);
			if(rs_trace.allsolid || rs_trace.startsolid || rs_trace.fraction != 1.0) 
				ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
		}
		goto VCHCANSEL;
	}
	//--------------------------------------------------------------------------------------
	//search for items
	if(!chedit->value && zc->second_target == NULL)
	{
		pickup_pri = false;			//pickup priority off
		k = false;

		zc->secondinterval++;
		//when tracing routes
		if(zc->route_trace && zc->secondinterval > 40)
		{
			for(i = zc->routeindex ; i < (zc->routeindex + 20); i++)
			{
				if(i >= CurrentIndex) break;
				if(Route[i].state == GRS_ITEMS)
				{
					if(Route[i].ent->solid == SOLID_TRIGGER)
					{
						pickup_pri = true;
						break;
					}
				}
			}
		}
		
		if(1/*!k*/)
		{
			if(zc->secondinterval > 40)
			{
				if(!(zc->zcstate & STS_WAITSMASK ))
				{
					Bot_SearchItems(ent);
					if(zc->second_target != NULL && pickup_pri)
					{
						for(i = zc->routeindex ; i < (zc->routeindex + 20); i++)
						{
							if(i >= CurrentIndex) break;
							if(Route[i].state == GRS_ITEMS)
							{
								if(Route[i].ent == zc->second_target)
								{
									zc->second_target = NULL;
									break;
								}
							}
						}						
					}
				}
			}
		}

		if(zc->secondinterval > 40/*zc->second_target != NULL*/ /*&& !k*/)
		{
			zc->secondinterval = Bot[zc->botindex].param[BOP_PICKUP] * 4;
			if(zc->secondinterval > 36) zc->secondinterval = 36;
			if(zc->secondinterval < 0) zc->secondinterval = 0;
		}

		if(ent->client->zc.objshot) goto VCHCANSEL; //object shot!!
	}

	//--------------------------------------------------------------------------------------
	//go up ladder
	//
	//
	//
	//	梯子を登る
	//
	//
	//--------------------------------------------------------------------------------------

	if(zc->zcstate & STS_LADDERUP)
	{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"ladder UP!! %f %i\n",zc->moveyaw,ent->waterlevel);
#endif
		if(ent->waterlevel > 1)
		{
/*			if(zc->route_trace )
			{
				Get_RouteOrigin(zc->routeindex,v);
				Bot_Watermove ( ent,pos,dist,upd)*/
			ent->velocity[2] = VEL_BOT_WLADRUP;
//			if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
		}
		else
		{
			ent->velocity[2] = VEL_BOT_LADRUP;
//			if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
		}

		VectorCopy(ent->mins,trmin);
		trmin[2] += 20;

		yaw = zc->moveyaw * M_PI * 2 / 360;
		touchmin[0] = cos(yaw) * 32;//96 ;
		touchmin[1] = sin(yaw) * 32;//96 ;
		touchmin[2] = 0;
		
		VectorAdd(ent->s.origin,touchmin,touchmax);

		rs_trace = gi.trace (ent->s.origin, trmin/*ent->mins*/,ent->maxs, touchmax,ent, MASK_BOTSOLID/*MASK_PLAYERSOLID*/);

		plane = rs_trace.plane;

		if(!(rs_trace.contents & CONTENTS_LADDER) && !rs_trace.allsolid /*&& !rs_trace.startsolid*/)
		{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"ladder OFF1!!\ncont %x %x\nall %i\nstart %i\n",rs_trace.contents,i,rs_trace.allsolid,rs_trace.startsolid);
#endif
			if(ent->velocity[2] <= VEL_BOT_LADRUP && !ent->waterlevel) ent->velocity[2] = VEL_BOT_LADRUP;
			zc->zcstate &= ~STS_LADDERUP;
			ent->moveinfo.speed = 0.25;
			if(zc->route_trace)
			{
				Get_RouteOrigin(zc->routeindex,v);
				if(VectorLength(v) > 32)
				{
					VectorSubtract(v,ent->s.origin,v);
					zc->moveyaw = Get_yaw(v);
					if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw;
				}
				else zc->routeindex++;
			}
		}
		else
		{	
//pon
			if(!rs_trace.allsolid)
			{
				VectorCopy(rs_trace.endpos,ent->s.origin);
			}

//pon
//			ent->moveinfo.speed = 1.0;
			VectorCopy(ent->s.origin,touchmin);
			touchmin[2] += 8;
			
			rs_trace = gi.trace (ent->s.origin, ent->mins,ent->maxs, touchmin,ent, MASK_BOTSOLID/*MASK_PLAYERSOLID*/ );

			x = rs_trace.endpos[2] - ent->s.origin[2];
			
			if(ent->waterlevel )
			{
				ent->s.origin[2] += x;
			}
			else
			{
				ent->s.origin[2] += x;
			}			
			
			e = rs_trace.ent;

			if(x == 0/*VectorCompare(ent->s.origin,ent->s.old_origin)*/) 
			{
				x = Get_yaw(plane.normal);

				//right
				VectorCopy(ent->s.origin,v);
				yaw = x + 90;
				if(yaw > 180) yaw -= 360; 
				yaw = yaw * M_PI * 2 / 360;
				touchmin[0] = cos(yaw) * 48 ;
				touchmin[1] = sin(yaw) * 48 ;
				touchmin[2] = 0;
				VectorAdd(ent->s.origin,touchmin,trmin);

				VectorCopy(trmin,trmax);
				trmin[2] += 32;
				trmax[2] += 64;
				rs_trace = gi.trace(trmin,NULL,NULL,trmax,ent,MASK_BOTSOLID);
				f1 = rs_trace.fraction;

				//left
				VectorCopy(ent->s.origin,v);
				iyaw = x -90 ;
				if(iyaw < 180) iyaw += 360; 
				iyaw = iyaw * M_PI * 2 / 360;
				touchmin[0] = cos(iyaw) * 48 ;
				touchmin[1] = sin(iyaw) * 48 ;
				touchmin[2] = 0;
				VectorAdd(ent->s.origin,touchmin,trmin);

				VectorCopy(trmin,trmax);
				trmin[2] += 32;
				trmax[2] += 64;
				rs_trace = gi.trace(trmin,NULL,NULL,trmax,ent,MASK_BOTSOLID);
				f2 = rs_trace.fraction;

				x = 0.0;
				if(f1 == 1.0 && f2 != 1.0) x = yaw;
				else if(f1 != 1.0 && f2 == 1.0) x = iyaw;

				if(x != 0.0)
				{
					touchmin[0] = cos(x) * 4 ;
					touchmin[1] = sin(x) * 4 ;
					touchmin[2] = 0;
					VectorAdd(ent->s.origin,touchmin,trmin);
					rs_trace = gi.trace(ent->s.origin,ent->mins,ent->maxs,trmin,ent,MASK_BOTSOLID);
					if(rs_trace.startsolid || rs_trace.allsolid) x = 0;
					else VectorCopy(rs_trace.endpos,ent->s.origin);
				}
				
				if(x == 0.0)
				{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"ladder OFF2!!\n");
#endif
					k = 0;
					if(e)
					{
						if(Q_stricmp (e->classname, "func_door") == 0)
						{
							if(e->moveinfo.state == PSTATE_UP) k = true;
						}
					}
					if(!k)
					{
						zc->moveyaw += 180;
						if(zc->moveyaw > 180) zc->moveyaw -= 360;
						zc->zcstate &= ~STS_LADDERUP;
						ent->moveinfo.speed = 0.25;
					}
				}
			}
		}
			
		if(zc->zcstate & STS_LADDERUP)
		{
			if(zc->route_trace )
			{
				Get_RouteOrigin(zc->routeindex,v);
				if(v[2] < ent->s.origin[2])
				{
					VectorSubtract(ent->s.origin,v,vv);
					vv[2] = 0;
					if(VectorLength(vv) < 32) zc->routeindex++;
				}
			}


			ent->velocity[0] = 0;
			ent->velocity[1] = 0;
			goto VCHCANSEL_L;
		}
	}

	//--------------------------------------------------------------------------------------
	//bot's true moving yaw,yaw pitch set
	// j is used ground entity check section
	//
	//
	//
	//	移動方向決定
	//
	//
	//--------------------------------------------------------------------------------------

	j = 0;
	if(ent->groundentity && ent->waterlevel <= 1 && trace_priority < TRP_ANGLEKEEP) ent->s.angles[PITCH] = 0;
	if(zc->second_target != NULL )
	{
		if((zc->second_target->s.origin[2] - ent->s.origin[2]) > 32 && !ent->waterlevel)
		{
			x = zc->second_target->moveinfo.start_origin[2] - ent->s.origin[2];
			if(x <= 32 && x > -24 && Bot_trace2 (ent,zc->second_target->moveinfo.start_origin))
			{
				VectorSubtract(zc->second_target->moveinfo.start_origin,ent->s.origin,temppos);
				k = false;
				yaw = temppos[2];
				temppos[2] = 0;
				x = VectorLength(temppos);

				if(yaw < -32 && x < 32) k = true;
				
				if(!k)
				{
					if(!ent->groundentity && !ent->waterlevel)
					{
						if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = Get_yaw(temppos);
					}
					else if(ent->groundentity || ent->waterlevel )
					{
						if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
						if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw;
					}

					if(x < dist && fabs(temppos[2]) < 24) dist = x;//pon 
				}
				j = -1;
			}
		}
		else 
		{
			VectorSubtract(zc->second_target->s.origin,ent->s.origin,temppos);
			if(ent->waterlevel && !ent->groundentity && trace_priority < TRP_ANGLEKEEP) ent->s.angles[PITCH] = Get_pitch(temppos); 

			if(!ent->groundentity && !ent->waterlevel && trace_priority < TRP_ANGLEKEEP)
			{
				temppos[2] = 0;
				if(VectorLength(temppos) > 32)
				{
					if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = Get_yaw(temppos);
				}
			}
			else if(ent->groundentity || ent->waterlevel )
			{
				k = false;
				yaw = temppos[2];
				temppos[2] = 0;
				x = VectorLength(temppos);

				if(yaw < -32 && x < 32) k = true;

				if(!k)
				{
					if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);	//set the movin' yaw
					if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw;
					if(x < dist && fabs(yaw) < JumpMax) dist = x; 
				}
			}
			j = -1;
		}
	}
	else
	{
		if(ent->groundentity && !zc->route_trace) 
		{
			if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = ent->s.angles[YAW];
		}
		else if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw ;
	}

/*	if(zc->first_target != NULL)
	{
		VectorSubtract(zc->first_target->s.origin,ent->s.origin,temppos);
		ent->s.angles[YAW] = Get_yaw(temppos);	//set the model's yaw
		ent->s.angles[PITCH] = Get_pitch(temppos);
	}
*/
	//チームプレイ時のルーチン
	if(ctf->value ||((int)(dmflags->value) & (DF_MODELTEAMS | DF_SKINTEAMS)))
	{
		if(ctf->value)
		{
			if(zc->ctfstate == CTFS_SUPPORTER)
			{
				if(zc->followmate)
				{
					if(zc->followmate->inuse)
						if(zc->followmate->client->zc.ctfstate != CTFS_CARRIER)
						{
							zc->ctfstate = CTFS_OFFENCER;
							zc->followmate = NULL;						
						}
				}

				if(zc->second_target == NULL) j = 1;
			}
			else j = 0;	
		}
		else
		{
			if(zc->tmplstate == TMS_FOLLOWER && zc->second_target == NULL) j = 1;
			else j = 0;		
		}

		if(j/*zc->tmplstate == TMS_FOLLOWER && zc->second_target == NULL*/)
		{
			if(zc->followmate)
			{
				k = Bot_traceS(ent,zc->followmate);
				if(k || zc->route_trace) zc->matelock = level.time + FRAMETIME * 5;
				if(!zc->followmate->inuse || zc->followmate->deadflag || zc->matelock <= level.time)
				{
					if(ctf->value) zc->ctfstate = CTFS_OFFENCER;
					else zc->tmplstate = TMS_NONE;
					zc->followmate = NULL;
				}
				else
				{
					VectorSubtract(zc->followmate->s.origin,ent->s.origin,v);
					if(VectorLength(v) < 200) 
					{
						if(k && zc->followmate->client->zc.route_trace
							&& (zc->followmate->client->zc.routeindex - 2) > 0
							&& (ent->svflags & SVF_MONSTER))
						{
							zc->routeindex = zc->followmate->client->zc.routeindex - 2;
							zc->route_trace = true;
							if(zc->followmate->client->zc.havetarget)
							{
								zc->targetindex = zc->followmate->client->zc.targetindex;
							}
						}
						else if(!(ent->svflags & SVF_MONSTER))
						{
							zc->moveyaw = Get_yaw(v);
							//if(VectorLength(v) < 100) trace_priority = TRP_ALLKEEP;
							//else trace_priority = TRP_MOVEKEEP;
						}
						if(VectorLength(v) < 100)
						{
							if(!v[0]) v[0] = 1;
							if(!v[1]) v[1] = 1;
							v[0] *= -1;
							v[1] *= -1;
							if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(v);
							if(trace_priority < TRP_ANGLEKEEP)
							{
								ent->s.angles[YAW] = zc->moveyaw;
								ent->s.angles[PITCH] = Get_pitch(v);
							}
						}
						else if(trace_priority < TRP_MOVEKEEP)
						{
							goto VCHCANSEL;
						}
					}
					else if(ent->groundentity || ent->waterlevel )
					{
						if(zc->followmate->client->zc.route_trace && (ent->svflags & SVF_MONSTER)) zc->routeindex = zc->followmate->client->zc.routeindex;
						else
						{
							if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(v);
							if(trace_priority < TRP_ANGLEKEEP)
							{
								ent->s.angles[YAW] = zc->moveyaw;
								ent->s.angles[PITCH] = Get_pitch(v);
							}
						}
					}
				}
			}
			else
			{
				if(ctf->value) zc->ctfstate = CTFS_OFFENCER;
				else zc->tmplstate = TMS_NONE;
			}
		}
	}

	//ctf route index fix
	if(ctf->value && !chedit->value)
	{
		j = 0;
		if(ent->client->resp.ctf_team == CTF_TEAM1)
		{
//if(zc->ctfstate == CTFS_CARRIER)
//			gi.bprintf(PRINT_HIGH,"I am carrierX!!\n");
			if(zc->ctfstate == CTFS_DEFENDER 
				|| zc->ctfstate == CTFS_CARRIER
				|| zc->ctfstate == CTFS_SUPPORTER) j = FOR_FLAG1;
			else j = FOR_FLAG2;
		}
		else if(ent->client->resp.ctf_team == CTF_TEAM2)
		{
			if(zc->ctfstate == CTFS_DEFENDER 
				|| zc->ctfstate == CTFS_CARRIER
				|| zc->ctfstate == CTFS_SUPPORTER) j = FOR_FLAG2;
			else j = FOR_FLAG1;
		}

		if(zc->route_trace)
		{
			if(Route[zc->routeindex].state < GRS_ITEMS
				&& Route[zc->routeindex].linkpod[MAXLINKPOD - 1])
			{
				k = Route[zc->routeindex].linkpod[MAXLINKPOD - 1];
				if(j == FOR_FLAG1)
				{
					if(k & CTF_FLAG2_FLAG) 
					{
//gi.bprintf(PRINT_HIGH,"Wrong way 1\n");
						for(i = 0;i < (MAXLINKPOD - 1);i++)
						{
							if(!Route[zc->routeindex].linkpod[i]) break;
							k = Route[Route[zc->routeindex].linkpod[i]].linkpod[MAXLINKPOD - 1];
							if(!(k & CTF_FLAG2_FLAG))
							{
								zc->routeindex = Route[zc->routeindex].linkpod[i];// zc->route_trace = false;
								zc->havetarget = false;
//gi.bprintf(PRINT_HIGH,"fixed for flag 1\n");
							}
						}
					}
					else if(!zc->havetarget && zc->ctfstate == CTFS_CARRIER)
					{
						zc->havetarget = true;
						zc->targetindex = Route[zc->routeindex].linkpod[MAXLINKPOD - 1] & 0x7FFF;
					}
				}
				else if(j == FOR_FLAG2)
				{
					if(!(k & CTF_FLAG2_FLAG))
					{
//gi.bprintf(PRINT_HIGH,"Wrong way 2\n");
						for(i = 0;i < (MAXLINKPOD - 1);i++)
						{
							if(!Route[zc->routeindex].linkpod[i]) break;
							k = Route[Route[zc->routeindex].linkpod[i]].linkpod[MAXLINKPOD - 1];
							if(k & CTF_FLAG2_FLAG)
							{
								zc->routeindex = Route[zc->routeindex].linkpod[i];// zc->route_trace = false;
								zc->havetarget = false;
//gi.bprintf(PRINT_HIGH,"fixed for flag 2\n");
							}
						}
					}
					else if(!zc->havetarget && zc->ctfstate == CTFS_CARRIER)
					{
						zc->havetarget = true;
						zc->targetindex = Route[zc->routeindex].linkpod[MAXLINKPOD - 1] & 0x7FFF;
					}
				}
			}
		}
	}

	if(1/*!(zc->zcstate & STS_WAITSMASK)*/)
	{
		//ルートトレース用index検索
		if(!zc->route_trace && zc->rt_releasetime <= level.time)
		{
			//zc->routeindex;
			if(zc->routeindex >= CurrentIndex) zc->routeindex = 0;
			//fix route index
			for(i = 0;i < CurrentIndex && i < MAX_SEARCH;i++)
			{
				if(Route[zc->routeindex].state == GRS_GRAPHOOK)
				{
					while(1)
					{
						++zc->routeindex;
						if(zc->routeindex >= CurrentIndex){i = CurrentIndex; break;}
						if(Route[zc->routeindex].state == GRS_GRAPRELEASE) {++zc->routeindex; break;}
					}
					continue;
				}
				else if(Route[zc->routeindex].state == GRS_GRAPRELEASE) {++zc->routeindex; continue;}
				else if(ctf->value && !chedit->value)
				{
					if(Route[zc->routeindex].state < GRS_ITEMS
						&& Route[zc->routeindex].linkpod[MAXLINKPOD - 1])
					{
						k = Route[zc->routeindex].linkpod[MAXLINKPOD - 1];
						if(j == FOR_FLAG1)
						{
							if(k & CTF_FLAG2_FLAG)
							{
								zc->routeindex = (k & 0x7FFF);
//gi.bprintf(PRINT_HIGH,"skipped to flag 1 %x\n",k);
							}
						}
						else if(j == FOR_FLAG2)
						{
							if(!(k & CTF_FLAG2_FLAG))
							{
								zc->routeindex = (k & 0x7FFF);
//gi.bprintf(PRINT_HIGH,"skipped to flag 2 %x\n",k);
							}
						}
					}
				}
				Get_RouteOrigin(zc->routeindex,v);
//				VectorSubtract(Route[k].Pt,ent->s.origin,temppos);
				if(Route[zc->routeindex].state <= GRS_ITEMS && TraceX(ent,v))
				{
					if(fabs(v[2] - ent->s.origin[2]) <= JumpMax || zc->waterstate == WAS_IN)
					{
						zc->route_trace = true;
						zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
						break;
					}
				}
				if(++zc->routeindex >= CurrentIndex) zc->routeindex = 0;
			}
		}
		else if(zc->route_trace)
		{
			if(Route[zc->routeindex].state == GRS_ONDOOR)
			{
				if(1/*!Route[zc->routeindex].ent->union_ent*/)
				{
					it_ent = Route[zc->routeindex].ent;
					if(zc->routeindex + 1 < CurrentIndex )
					{
						Get_RouteOrigin(zc->routeindex + 1,v);
						zc->route_trace = false;
						j = TraceX(ent,v);
						zc->route_trace = true;
						if((!j || (v[2] - ent->s.origin[2]) > JumpMax )&& it_ent->union_ent) 
						{

							k = false;
							if((it_ent->union_ent->s.origin[2] - ent->s.origin[2]) > JumpMax) k = true;

							VectorSubtract(it_ent->union_ent->s.origin,ent->s.origin,temppos);
							yaw = Get_yaw(temppos);
							if(trace_priority < TRP_ANGLEKEEP)
							{
								ent->s.angles[PITCH] = Get_pitch(temppos);
								ent->s.angles[YAW] = yaw;
							}
							temppos[2] = 0;
							x = VectorLength(temppos);

							if( x == 0/*< dist*/ || k)
							{
								if(it_ent->nextthink >= level.time) zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
								goto VCHCANSEL;	//if center position move cancel
							}
							if(x < dist) dist = x;
							if(it_ent->nextthink > level.time) zc->rt_locktime = it_ent->nextthink + FRAMETIME * POD_LOCKFRAME;
							else zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
							if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = yaw;
							goto GOMOVE;
						}
					}
					
				}
				zc->routeindex++;
			}

			if(zc->routeindex < CurrentIndex)
			{
				Get_RouteOrigin(zc->routeindex,v);
/*				if(Route[zc->routeindex].state == GRS_ITEMS)
				{
					if(Route[zc->routeindex].ent->solid == SOLID
				}*/

				k = false;
				if(Route[zc->routeindex].state == GRS_PUSHBUTTON)
				{
					it_ent = Route[zc->routeindex].ent;
					if(it_ent->health && (it_ent->takedamage || it_ent->moveinfo.state != PSTATE_TOP))
					{
						k = 2;
					}
					else if(it_ent->health)
					{
						zc->routeindex++;
						if(zc->routeindex < CurrentIndex) Get_RouteOrigin(zc->routeindex,v);
					} 
				}
				else
				{
					//VectorCopy(ent->mins,touchmin);
					//touchmin[2] += 20;
					VectorSet(touchmax,16,16,4);
					VectorSet(touchmin,-16,-16,0);
					rs_trace = gi.trace(ent->s.origin,touchmin,touchmax,v,ent,MASK_SHOT);
					if(rs_trace.fraction != 1.0 && rs_trace.ent)
					{
						if((rs_trace.ent->health || rs_trace.ent->takedamage) 
							&& rs_trace.ent->classname[0] != 'p'
							&& rs_trace.ent->classname[0] != 'b')
						{
//gi.bprintf(PRINT_HIGH,"shushu!\n");
							zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
							it_ent = rs_trace.ent;
							k = true;
						}
					}
				}

				//トリガを撃つ
				if(k && !(ent->client->buttons & BUTTON_ATTACK))
				{
//gi.bprintf(PRINT_HIGH,"ooooooo!\n");
					trmin[0] = (it_ent->absmin[0] + it_ent->absmax[0])/2;
					trmin[1] = (it_ent->absmin[1] + it_ent->absmax[1])/2;
					trmin[2] = (it_ent->absmin[2] + it_ent->absmax[2])/2;

					//if button
					if(k == 2)
					{
						VectorSet(touchmin, 0, 0, ent->viewheight-8);
						VectorAdd(ent->s.origin,touchmin,touchmin);

						rs_trace = gi.trace(it_ent->union_ent->s.origin,NULL,NULL,trmin,it_ent->union_ent,MASK_SHOT);
						VectorSubtract(rs_trace.endpos,ent->s.origin,trmax);
					}
					else VectorSubtract(v,ent->s.origin,trmax);

//gi.bprintf(PRINT_HIGH,"shoot!\n");
					//爆発モノの時は持ち替え
					i = Get_KindWeapon(ent->client->pers.weapon);
					if(!zc->first_target && it_ent->takedamage)
					{
						if(i == WEAP_GRENADES 
							|| i == WEAP_GRENADELAUNCHER 
							|| i == WEAP_ROCKETLAUNCHER 
							|| i == WEAP_PHALANX
							|| i == WEAP_BFG)
						{
							item = Fdi_BLASTER;//FindItem("Blaster");
							item->use(ent,item);
//if(ent->client->newweapon) gi.bprintf(PRINT_HIGH,"selected %s\n",ent->client->newweapon->pickup_name);
						}
					}
					if(!zc->first_target || it_ent->takedamage)
					{
						ent->s.angles[YAW] = Get_yaw(trmax);
						ent->s.angles[PITCH] = Get_pitch(trmax);
					}
					if(it_ent->takedamage) ent->client->buttons |= BUTTON_ATTACK;
					if(k == 2)
					{
						if(it_ent->moveinfo.state != PSTATE_TOP) goto VCHCANSEL;
					}
					else
					{
						if(!TraceX(ent,v)) goto VCHCANSEL;
					}
					//if(j)goto VCHCANSEL;
				}

				if(Route[zc->routeindex].state == GRS_ONTRAIN && !zc->waterstate /*< WAS_IN*/
					/*ent->groundentity*/)
				{
					Get_RouteOrigin(zc->routeindex -1 ,trmin);
					if((trmin[2] - ent->s.origin[2]) > /*2*/JumpMax
						&& (v[2] - ent->s.origin[2]) > JumpMax
						&& ent->waterlevel < 3)
					{
						zc->route_trace = false;
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 10\n");
#endif
					}
/*					if(!Q_stricmp(ent->groundentity->classname, "func_train"))
					{ 
						VectorCopy(ent->groundentity->union_ent->s.origin,v);
						if(VectorLength(v) < 16 && (zc->routeindex + 1) < CurrentIndex)
						{
							zc->routeindex++;
							Get_RouteOrigin(zc->routeindex,v);
						}

					}*/

				}
				if(zc->waterstate == WAS_IN) f2 = 20;
				else if(ent->groundentity) f2 = -8;
				else f2 = 0;
				if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) f1 = -16;
				else
				{
					if(zc->waterstate == WAS_IN) f1 = 24;
					else if(/*zc->waterstate == WAS_FLOAT*/ent->waterlevel && ent->waterlevel < 3)
					{
						if(v[0] == ent->s.origin[0] && v[1] == ent->s.origin[1]) f1 = -300;
						else f1 = -(JumpMax + 64);
					}
					else f1 = -(JumpMax + 64);
				}
//到達チェック
				if( Route[zc->routeindex].state == GRS_ONROTATE) yaw = -48;
				else yaw = 12;
				if(v[0] <= (ent->absmax[0] - yaw) && v[0] >= (ent->absmin[0] + yaw))
				{
					if(v[1] <= (ent->absmax[1] - yaw) && v[1] >= (ent->absmin[1] + yaw))
					{
						if((v[2] <= (ent->absmax[2] - f1) && v[2] >= (ent->absmin[2] + f2))
							|| Route[zc->routeindex].state == GRS_ONROTATE
							/*|| zc->waterstate == WAS_FLOAT*/)
						{
							if(zc->routeindex < CurrentIndex /*&& TraceX(ent,Route[zc->routeindex + 1].Pt)*/)
							{
//アイテムリンクチェック1>>
								if(Route[zc->routeindex].state <= GRS_ITEMS)
								{
									if(zc->havetarget)
									{
										for(i = 0;i < (MAXLINKPOD - (ctf->value != 0));i++)
										{
											k = Route[zc->routeindex].linkpod[i];
											if(!k) break;
//gi.bprintf(PRINT_HIGH,"tryto change index1\n");
											if(k > zc->routeindex && k < zc->targetindex)
											{
//gi.bprintf(PRINT_HIGH,"change index1\n");		
												if(1/*!ctf->value*/)
												{
													zc->routeindex = k;
													break;
												}
											}
										}
									}
									else if(random() < 0.2 && !ctf->value)
									{
										for(i = 0;i < (MAXLINKPOD - (ctf->value != 0));i++)
										{
											k = Route[zc->routeindex].linkpod[i];
											if(!k) break;
											if(k > zc->routeindex && k < zc->targetindex)
											{
												if(random() < 0.5)
												{
													zc->routeindex = k;
													break;
												}
											}
										}									
									}
								}
//アイテムリンクチェック<<
								zc->routeindex++;
								//not a normal pod
								if(zc->routeindex < CurrentIndex)
								{
									if(Route[zc->routeindex].state != GRS_NORMAL && Route[zc->routeindex].ent)
									{
										//when items
										if(0/*Route[zc->routeindex].state == GRS_ITEMS*/)
										{
											zc->second_target = Route[zc->routeindex].ent;
											//zc->routeindex++;
										}
									}
								}
								else zc->routeindex = 0;
							}
						}
					}
				}

				if(zc->routeindex < CurrentIndex 
					&& trace_priority && zc->second_target == NULL)
				{
					if(1/*TraceX(ent,Route[zc->routeindex].Pt)*/)
					{
						Get_RouteOrigin(zc->routeindex,v);

						VectorSubtract(v,ent->s.origin,temppos);
						if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[PITCH] = Get_pitch(temppos);

						k = false;
//						if(zc->waterstate != WAS_IN && temppos[2] < 32) k = true;
//						else if(zc->waterstate == WAS_IN) k = true;

						if(ent->groundentity /*|| ent->waterlevel ) &&  
							/*temppos[2] < 32 || zc->waterstate != WAS_IN)*/ || ent->waterlevel/*zc->waterstate*/ )
						{
							k = false;
							yaw = temppos[2];
							temppos[2] = 0;
							x = VectorLength(temppos);
//							if(yaw > JumpMax) k = true;

							if(!k)
							{
								k = false;
								if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);	//set the movin' yaw
								if((ent->groundentity || ent->waterlevel) && trace_priority < TRP_ANGLEKEEP) {ent->s.angles[YAW] = zc->moveyaw; k = true;}

								if(x < dist && fabs(yaw) < 20/*JumpMax*/&& k)
								{
									iyaw = Get_yaw(temppos);
									i = Bot_moveT (ent,iyaw,temppos,x,&bottom);
									rs_trace = gi.trace(/*ent->s.origin*/v,ent->mins,ent->maxs,v,ent,MASK_BOTSOLIDX);
									
									if(Route[zc->routeindex].state == GRS_ITEMS && !i)
									{
										if(x < 30) zc->routeindex++;
									}

									else if((Route[zc->routeindex].state == GRS_ITEMS
										|| Route[zc->routeindex].state == GRS_NORMAL)
										&& !rs_trace.allsolid && !rs_trace.startsolid
										&& HazardCheck(ent,v)
										&& fabs(bottom) < 20 && i && !ent->waterlevel/*&& rs_trace.fraction == 1.0*/)
									{
										j = false;
										if(v[2] < ent->s.origin[2] && bottom < 0) j = true;
										else if(v[2] >= ent->s.origin[2] && bottom >= 0) j = true;
										if(j)
										{
											VectorCopy(temppos,ent->s.origin);
											VectorCopy(v,trmin);
											dist -= x;
//アイテムリンクチェック2>>
											if(Route[zc->routeindex].state <= GRS_ITEMS)
											{
												if(zc->havetarget)
												{
													for(i = 0;i < (MAXLINKPOD - (ctf->value != 0));i++)
													{
														j = Route[zc->routeindex].linkpod[i];
														if(!j) break;
//gi.bprintf(PRINT_HIGH,"tryto change index2\n");
														if(j > zc->routeindex && j < zc->targetindex)
														{
//gi.bprintf(PRINT_HIGH,"change index2\n");
															zc->routeindex = j;
															break;
														}
													}
												}
											}
//アイテムリンクチェック<<
											zc->routeindex++;
											if(i == 2) ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
										
											Get_RouteOrigin(zc->routeindex,v);
											VectorSubtract(v,ent->s.origin,temppos);
											if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[PITCH] = Get_pitch(temppos);
											if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
											if(k && trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw;
										}
									}
									else if((Route[zc->routeindex].state == GRS_ITEMS
										|| Route[zc->routeindex].state == GRS_NORMAL)
										&& fabs(bottom) < 20 && ent->waterlevel
										/*&& !(zc->zcstate & STS_LADDERUP)*/)
									{
										j = false;
										if(v[2] < ent->s.origin[2] && bottom < 0) j = true;
										else if(v[2] >= ent->s.origin[2] && bottom >= 0) j = true;
										if(j)
										{
											VectorCopy(temppos,ent->s.origin);
											//VectorCopy(v,ent->s.origin);
											VectorCopy(v,trmin);
											dist -= x;
											zc->routeindex++;
											Get_RouteOrigin(zc->routeindex,v);
											VectorSubtract(v,ent->s.origin,temppos);
											if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[PITCH] = Get_pitch(temppos);
											if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
											if(k && trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = zc->moveyaw;
										}
										else dist = x;
									}
									else dist = x; 
								}
								else if(x < dist) dist = x;
							}

							k = false;
							if((zc->routeindex - 1) >= 0 &&
								(Route[zc->routeindex].state == GRS_ONPLAT 
								|| Route[zc->routeindex].state == GRS_ONTRAIN))
							{
								Get_RouteOrigin(zc->routeindex - 1,v);
								if(fabs(v[2] - ent->s.origin[2]) <= JumpMax)
								{
									if(zc->waterstate < WAS_IN
										/*&& Route[zc->routeindex].ent->trainteam == NULL*/
										&& Route[zc->routeindex].ent->nextthink > level.time) k = true;
								}

							}
							if(k && !(zc->zcstate & STS_WAITS)) 
							{
								if((zc->routeindex + 1) < CurrentIndex)
								{
									Get_RouteOrigin(zc->routeindex + 1,v);
									if((v[2] - ent->s.origin[2]) > JumpMax)
									{
										if((Route[zc->routeindex].ent->union_ent->s.origin[2]
											- ent->s.origin[2]) > JumpMax
											/*|| !TraceX(ent,v)*/)
										{
											zc->waitin_obj = Route[zc->routeindex].ent;
											zc->zcstate |= STS_W_COMEPLAT;
											k = false;
											for(i = 1;i <=3;i++)
											{
												if(zc->routeindex - i >= 0)
												{
													Get_RouteOrigin(zc->routeindex - i,v);
													if(zc->waitin_obj->absmax[0] < (v[0] + ent->mins[0])) k = true; 
													else if(zc->waitin_obj->absmax[1] < (v[1] + ent->mins[1])) k = true;
													else if(zc->waitin_obj->absmin[0] > (v[0] + ent->maxs[0])) k = true;
													else if(zc->waitin_obj->absmin[1] > (v[1] + ent->maxs[1])) k = true;
													if(k) break;
												}
											}
											if(k) VectorCopy(v,zc->movtarget_pt);
											else Get_RouteOrigin(zc->routeindex - 1,zc->movtarget_pt);

											goto VCHCANSEL;
										}
									}
								}
							}

						}
						//ent->s.angles[YAW] = zc->moveyaw;
					}
				}
				else if(zc->routeindex >= CurrentIndex)
				{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 6\n"); //ppx
#endif
					zc->routeindex = 0;
					zc->route_trace = false;				
				}
			}
			else
			{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 7\n"); //ppx
#endif
				zc->routeindex = 0;
				zc->route_trace = false;				
			}
		}
	}
	else
	{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"OFF 8\n"); //ppx
#endif
		zc->route_trace = false;
	}

	//--------------------------------------------------------------------------------------
	//ground entity check
	//
	//
	//
	//	あしもと確認
	//
	//
	//--------------------------------------------------------------------------------------
	
	if(!(zc->zcstate & STS_W_DOOROPEN ) && (!ent->groundentity || ent->groundentity != zc->waitin_obj))
	{
		k = false;
		if(zc->waitin_obj) if(Q_stricmp (zc->waitin_obj->classname,"func_door")) k = true;

		if(!k)
		{
			zc->zcstate &= ~STS_WAITS;
			zc->waitin_obj = NULL; 
		}
	}

	if(ent->groundentity && /*!j &&*/ !(zc->zcstate & STS_WAITS) )
	{
		it_ent = ent->groundentity;
		if( it_ent->classname[0] == 'f')
		{
			if(Q_stricmp (it_ent->classname, "func_plat") == 0)
			{
/*if(it_ent->moveinfo.state == PSTATE_UP && it_ent->nextthink <= level.time )
gi.bprintf(PRINT_HIGH,"aw shit!!\n");*/
				if(it_ent->pos1[2] > it_ent->pos2[2] 
					&& ((it_ent->moveinfo.state == PSTATE_UP && it_ent->velocity[2] > 0 ) || it_ent->moveinfo.state == PSTATE_BOTTOM)
					/*&& it_ent->s.origin[2] != it_ent->s.old_origin[2]*/)
				{
//gi.bprintf(PRINT_HIGH,"osssre onplat!!\n");
					zc->waitin_obj = it_ent;
					zc->zcstate |= STS_W_ONPLAT;
					if(zc->route_trace)
					{
//gi.bprintf(PRINT_HIGH,"ore onplat!!\n");
						if(Route[zc->routeindex].ent == zc->waitin_obj
							&& Route[zc->routeindex].state == GRS_ONPLAT)
						{
//gi.bprintf(PRINT_HIGH,"YEAH onplat!!\n");
							if(zc->waitin_obj->union_ent->s.origin[2] > (ent->s.origin[2] + 32))
							{
								zc->zcstate &= ~STS_W_ONPLAT;
								zc->zcstate |= STS_W_COMEPLAT;
							}
							else zc->routeindex++;
						}
					/*	for(i = 0;i < 10;i++)
						{
							if((zc->routeindex + i) >= CurrentIndex) break;
							if(!Route[zc->routeindex + i].index) break;
							if(Route[zc->routeindex + i].state == GRS_ONPLAT 
								&& Route[zc->routeindex + i].ent == zc->waitin_obj)
							{
								zc->routeindex += i + 1;
								break;
							}
						}*/
					}
				}
			}
			//on train
			else if(Q_stricmp (it_ent->classname, "func_train") == 0
				&& it_ent->nextthink >= level.time 
				&& ((it_ent->s.origin[2] - it_ent->s.old_origin[2]) > 0
				|| zc->route_trace))
//				&& abs(it_ent->moveinfo.start_origin[2] - it_ent->moveinfo.end_origin[2]) > 54)
			{
//gi.bprintf(PRINT_HIGH,"challenge!!\n");
				//route trace on
				if(zc->route_trace && zc->routeindex > 0)
				{
					j = false;
					k = zc->routeindex - 1;
					for(i = 0;i < 3;i++)
					{
						if((k + i) < CurrentIndex)
						{
							if(Route[k + i].state == GRS_ONTRAIN)
							{
								if(Route[k + i].ent == it_ent) j = true;
								else if(it_ent->trainteam != NULL)
								{
									e = it_ent->trainteam; 
									while(1)
									{
										if(e == it_ent)
										{
											break;
										}
										if(e == Route[k + i].ent)
										{
											j = true;
											it_ent = e;
											Route[k + i].ent = e;
											break;
										}
										e = e->trainteam;
									}
								}
								else if(/*e*/it_ent->target_ent)
								{
									if(VectorCompare(Route[k + i].Tcourner,/*e*/it_ent->target_ent->s.origin))
									{
										j = true;
										//it_ent = e;
										break;									
									}
								}
								if(j) break;
							}
						}
						else break;
					}
					if(j)
					{
//gi.bprintf(PRINT_HIGH,"On train1!!\n");
						zc->zcstate |= STS_W_ONTRAIN;
						zc->waitin_obj = it_ent;
						zc->routeindex = k + i + 1;
					}
				}
/*					if(Route[zc->routeindex - 1].state == GRS_ONTRAIN
//						&& it_ent->trainteam == NULL
						&& it_ent == Route[zc->routeindex - 1].ent)
					{
							zc->zcstate |= STS_W_ONTRAIN;
							zc->waitin_obj = it_ent;
					}
					else if(Route[zc->routeindex].state == GRS_ONTRAIN
						&& it_ent == Route[zc->routeindex].ent
						&& zc->routeindex + 1 < CurrentIndex)
					{
						Get_RouteOrigin(zc->routeindex + 1,v);
						if(!TraceX(ent,v))
						{
							zc->zcstate |= STS_W_ONTRAIN;
							zc->waitin_obj = it_ent;
						}
						zc->routeindex++;
					}
					else if(Route[zc->routeindex].state == GRS_ONTRAIN
						&& it_ent->trainteam
						&& zc->routeindex + 1 < CurrentIndex)
					{
						Get_RouteOrigin(zc->routeindex + 1,v);
						if(!TraceX(ent,v))
						{
							k = false;
							e = it_ent->trainteam; 
							while(1)
							{
								if(e == it_ent) break;
								if(e == Route[zc->routeindex].ent)
								{
									k = true;
									break;
								}
								e = e->trainteam;
							}
							if(k)
							{
								zc->zcstate |= STS_W_ONTRAIN;
								zc->waitin_obj = it_ent;
								zc->routeindex++;
							}
						}
					}
				}*/
				else
				{
//					if(it_ent->moveinfo.start_origin[2] > it_ent->moveinfo.end_origin[2]) x = it_ent->moveinfo.end_origin[2];
//					else x = it_ent->moveinfo.start_origin[2];

					if((it_ent->s.origin[2] - it_ent->s.old_origin[2]) > 0
						/*|| (it_ent->s.origin[2] == it_ent->s.old_origin[2] && x == it_ent->s.origin[2])*/ )
					{
//gi.bprintf(PRINT_HIGH,"On train2!!\n");
						zc->zcstate |= STS_W_ONTRAIN;
						zc->waitin_obj = it_ent;
					}
					else if((it_ent->s.origin[2] - it_ent->s.old_origin[2]) > -2
						&& trace_priority && zc->second_target == NULL)
					{
//gi.bprintf(PRINT_HIGH,"On train3!!\n");
						zc->zcstate |= STS_W_ONTRAIN;
						zc->waitin_obj = it_ent;					
					}
					else zc->zcstate |= STS_W_DONT;
				}
			}
		}
	}

	if((zc->zcstate & STS_W_DONT) && ent->groundentity)
	{
		if(zc->zcstate & STS_W_ONPLAT)
		{
			if(Q_stricmp (ent->groundentity->classname, "func_plat"))
			{
				zc->zcstate &= ~STS_WAITS;
				zc->waitin_obj = NULL;
			}
		}
		else if(zc->zcstate & STS_W_ONTRAIN)
		{
			if(Q_stricmp (ent->groundentity->classname, "func_train"))
			{
				zc->zcstate &= ~STS_WAITS;
				zc->waitin_obj = NULL;
			}
		}
		else if(zc->zcstate & (STS_W_ONDOORUP | STS_W_ONDOORDWN))
		{
			if(Q_stricmp (ent->groundentity->classname, "func_door"))
			{
				zc->zcstate &= ~STS_WAITS;
				zc->waitin_obj = NULL;
			}
		}
		else 
		{
			zc->zcstate &= ~STS_WAITS;
			zc->waitin_obj = NULL;
		}
	}


	//on plat
	else if((
		(zc->zcstate & STS_W_ONPLAT)
		|| (zc->zcstate & STS_W_COMEPLAT)
		|| (zc->zcstate & STS_W_ONDOORUP)
		|| (zc->zcstate & STS_W_ONDOORDWN)) && !(zc->zcstate & STS_W_DONT))
	{
		k = false;
		//if door
		if(zc->zcstate & (STS_W_ONDOORUP | STS_W_ONDOORDWN) )
		{
			// up
			if(zc->zcstate & STS_W_ONDOORUP)
			{
				if(zc->waitin_obj->moveinfo.state == PSTATE_UP
					|| zc->waitin_obj->moveinfo.state == PSTATE_BOTTOM) k = true;
			}
			// down
			else 
			{
				if(zc->waitin_obj->moveinfo.state == PSTATE_TOP
					|| zc->waitin_obj->moveinfo.state == PSTATE_DOWN) k = true;				
			}
		}
		else if(zc->zcstate & STS_W_COMEPLAT) 
		{
			if(Route[zc->routeindex].state == GRS_ONTRAIN)
			{
				if(!TraceX(ent,/*zc->waitin_obj*/Route[zc->routeindex].ent->union_ent->s.origin)) k = true;
				if((/*zc->waitin_obj*/Route[zc->routeindex].ent->union_ent->s.origin[2]
								+ 8 - ent->s.origin[2]) > JumpMax) k = true;
			}
			else
			{
				if((zc->waitin_obj->union_ent->s.origin[2]
											- ent->s.origin[2]) > JumpMax) k = true;
			}		
//			if(zc->waitin_obj->velocity[2] == 0) k = false;
			if(zc->routeindex - 1 > 0 && zc->waterstate < WAS_IN)
			{
				Get_RouteOrigin(zc->routeindex -1 ,trmin);
				if((trmin[2] - ent->s.origin[2]) > JumpMax
						&& (v[2] - ent->s.origin[2]) > JumpMax)
//				Get_RouteOrigin(zc->routeindex - 1,v);
//				if((v[2] - ent->s.origin[2]) > JumpMax) 
					k = false;
			}
		}
		else 
		{
			if(/*!k &&*/ zc->waitin_obj->moveinfo.state == PSTATE_UP
				|| zc->waitin_obj->moveinfo.state == PSTATE_BOTTOM) k = true;

			if(zc->waitin_obj->moveinfo.state == PSTATE_BOTTOM) plat_go_up (zc->waitin_obj);

			if(zc->route_trace)
			{
				Get_RouteOrigin(zc->routeindex,v);
				if(ent->s.origin[2] > v[2] ) k = 2;
			}
		}
		//have target
		if(/*j ||*/ k != true)
		{
			if(k == 2) zc->zcstate |= STS_W_DONT;
			else
			{
				zc->zcstate &= ~STS_WAITS;
				zc->waitin_obj = NULL;
			}
		}
		else 
		{
			if(zc->zcstate & STS_W_COMEPLAT)
			{
				k = false;
				if(zc->routeindex -1 >0)
				{
					if(1/*Route[zc->routeindex - 1].state <= GRS_ITEMS*/)
					{
						//Get_RouteOrigin(zc->routeindex - 1,trmax);
						VectorCopy(zc->movtarget_pt,trmax);
						trmax[2] = 0;
						k = true;
					}
				}
				if(!k) goto VCHCANSEL;
			}
			else
			{
				trmax[0] = (zc->waitin_obj->absmin[0] + zc->waitin_obj->absmax[0]) / 2;
				trmax[1] = (zc->waitin_obj->absmin[1] + zc->waitin_obj->absmax[1]) / 2;
				trmax[2] = 0;
			}
			VectorSubtract(trmax,ent->s.origin,temppos);
			yaw = temppos[2];
			temppos[2] = 0;
			x = VectorLength(temppos);
			if( x == 0) goto VCHCANSEL;	//if center position move cancel
			if( x < dist) dist = x;
				
			if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
		}
	}
	// on train
	else if(zc->zcstate & STS_W_ONTRAIN)
	{
		i = false;
	
		if(zc->route_trace)
		{
			Get_RouteOrigin(zc->routeindex,v);

			if((zc->routeindex - 1) >= 0) 
			{
				if(Route[zc->routeindex - 1].state != GRS_ONTRAIN) i = true;
			}
			else i = true;

			if(TraceX(ent,v))
			{
				x = v[2] - /*zc->waitin_obj->union_ent->s.origin[2];*/ent->s.origin[2];
				if(x <= JumpMax)
				{
//gi.bprintf(PRINT_HIGH,"released!!! %f %i\n",x,Route[zc->routeindex].state);
					i = true;
				}
				else zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
			}
			else zc->rt_locktime = level.time + FRAMETIME * POD_LOCKFRAME;
		}
		else if(j || (zc->waitin_obj->s.origin[2] - zc->waitin_obj->s.old_origin[2]) <= 0 ) i = true;

		if(i)
		{
			zc->zcstate |= STS_W_DONT;
			zc->zcstate &= ~STS_WAITS;
//			zc->waitin_obj = NULL;
		}
		else 
		{
			k = false;
			if(zc->route_trace)
			{
				rs_trace = gi.trace(ent->s.origin,NULL,NULL,v,ent,MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/);
				if(rs_trace.ent == zc->waitin_obj )
				{
					rs_trace = gi.trace(v,NULL,NULL,ent->s.origin,ent,MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/);
					if(rs_trace.ent == zc->waitin_obj )
					{
						VectorSubtract(v,ent->s.origin,temppos);
						k = true;
					}
				}
			}
			if(!k)
			{
//gi.bprintf(PRINT_HIGH,"ponko1!\n");
				VectorCopy(zc->waitin_obj->union_ent->s.origin,trmax);
				//trmax[0] = (zc->waitin_obj->absmin[0] + zc->waitin_obj->absmax[0]) / 2;
				//trmax[1] = (zc->waitin_obj->absmin[1] + zc->waitin_obj->absmax[1]) / 2;
				trmax[2] += 8;
				VectorSubtract(trmax,ent->s.origin,temppos);
				yaw = temppos[2];
				temppos[2] = 0;
				x = VectorLength(temppos);

//gi.bprintf(PRINT_HIGH,"ponko2! %f < %f\n",x,dist);

				if( x < dist  /*MOVE_SPD_RUN*/)
				{
					dist = x;
//					goto VCHCANSEL;	//if center position move cancel
				}
			}
			if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
		}
		goto GOMOVE;
	}
	//wait for door open
	else if(zc->zcstate & STS_W_DOOROPEN)
	{
		if(!trace_priority
			|| zc->waitin_obj->moveinfo.state == PSTATE_TOP 
			/*|| (zc->waitin_obj->moveinfo.state == PSTATE_DOWN)*/)
		{
//gi.bprintf(PRINT_HIGH,"release %i %i\n",trace_priority,zc->waitin_obj->moveinfo.state);
			zc->zcstate &= ~STS_WAITS;
			zc->waitin_obj = NULL; 
		}
		else if(zc->waitin_obj->moveinfo.state == PSTATE_BOTTOM 
			|| zc->waitin_obj->moveinfo.state == PSTATE_UP)
		{
			VectorSubtract(zc->movtarget_pt,ent->s.origin,temppos);
			temppos[2] = 0;
			x = VectorLength(temppos);
			dist *= 0.25;
			if(x < 10 || VectorCompare(ent->s.origin,zc->movtarget_pt))
			{
//				if(abs(zc->waitin_obj->s.origin[2] - zc->waitin_obj->s.old_origin[2]) == 0) goto VCHCANSEL;

				if(!zc->waitin_obj->union_ent)
				{
					trmin[0] = (zc->waitin_obj->absmin[0] + zc->waitin_obj->absmax[0]) / 2;
					trmin[1] = (zc->waitin_obj->absmin[1] + zc->waitin_obj->absmax[1]) / 2;
					trmin[2] = (zc->waitin_obj->absmin[2] + zc->waitin_obj->absmax[2]) / 2;
				}
				else VectorCopy(zc->waitin_obj->union_ent->s.origin,trmin);
				trmin[2] += 8;
				VectorSubtract(trmin,ent->s.origin,temppos);
				if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
				if(trace_priority < TRP_ANGLEKEEP)
				{
					ent->s.angles[YAW] = zc->moveyaw;
					ent->s.angles[PITCH] = Get_pitch(temppos);
				}
				goto VCHCANSEL;
			}
			else 
			{
				if(trace_priority < TRP_MOVEKEEP) zc->moveyaw = Get_yaw(temppos);
				if(!zc->waitin_obj->union_ent)
				{
					trmin[0] = (zc->waitin_obj->absmin[0] + zc->waitin_obj->absmax[0]) / 2;
					trmin[1] = (zc->waitin_obj->absmin[1] + zc->waitin_obj->absmax[1]) / 2;
					trmin[2] = (zc->waitin_obj->absmin[2] + zc->waitin_obj->absmax[2]) / 2;
				}
				else VectorCopy(zc->waitin_obj->union_ent->s.origin,trmin);

				trmin[2] += 8;
				VectorSubtract(trmin,ent->s.origin,temppos);
				if(trace_priority < TRP_ANGLEKEEP)
				{
					ent->s.angles[YAW] = Get_yaw(temppos);
					ent->s.angles[PITCH] = Get_pitch(temppos);
				}
			}
		}
	}

//LADDER
	

	//--------------------------------------------------------------------------------------
	//ladder check
/*	front = NULL, left = NULL, right = NULL;
	k = false;
	if(zc->route_trace)
	{
		Get_RouteOrigin(zc->routeindex,v);
		if((v[2] - ent->s.origin[2]) >= 32) k = true;
			
	}
	if(k && !zc->first_target && !zc->second_target && !(ent->client->ps.pmove.pm_flags & PMF_DUCKED))
	{
		tempflag = false;

		VectorCopy(ent->mins,trmin);
		VectorCopy(ent->maxs,trmax);

		trmin[2] += 20;

		//front
		f1 = 32;
		if(zc->route_trace) f1 = 32;

		iyaw = zc->moveyaw;
		yaw = iyaw * M_PI * 2 / 360;
		touchmin[0] = cos(yaw) * f1;//28 ;
		touchmin[1] = sin(yaw) * f1;
		touchmin[2] = 0;

		VectorAdd(ent->s.origin,touchmin,touchmax);
		rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID );
		front = rs_trace.ent;

		if(rs_trace.contents & CONTENTS_LADDER) tempflag = true;

		//right
		if(!tempflag)
		{
			iyaw = zc->moveyaw + 90;
			if(iyaw > 180) iyaw -= 360;
			yaw = iyaw * M_PI * 2 / 360;
			touchmin[0] = cos(yaw) * 32 ;
			touchmin[1] = sin(yaw) * 32 ;
			touchmin[2] = 0;

			VectorAdd(ent->s.origin,touchmin,touchmax);
			rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent,  MASK_BOTSOLID );
			right = rs_trace.ent;

			if(rs_trace.contents & CONTENTS_LADDER) tempflag = true;
		}
		//left
		if(!tempflag)
		{
			iyaw = zc->moveyaw - 90;
			if(iyaw < -180) iyaw += 360;
			yaw = iyaw * M_PI * 2 / 360;
			touchmin[0] = cos(yaw) * 32 ;
			touchmin[1] = sin(yaw) * 32 ;
			touchmin[2] = 0;

			VectorAdd(ent->s.origin,touchmin,touchmax);
			rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID );
			left = rs_trace.ent;

			if(rs_trace.contents & CONTENTS_LADDER)	tempflag = true;
		}

		//ladder
		if(tempflag)
		{
			VectorCopy(rs_trace.endpos,trmax);
			VectorCopy(trmax,touchmax);
			touchmax[2] += 8190;
			rs_trace = gi.trace (temppos, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID );

			VectorCopy(rs_trace.endpos,temppos);
			VectorAdd(rs_trace.endpos,touchmin,touchmax);
			rs_trace = gi.trace (temppos, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID);
			
			if(!(rs_trace.contents & CONTENTS_LADDER) && rs_trace.fraction)
			{
//	gi.WriteByte (svc_temp_entity);
//	gi.WriteByte (TE_RAILTRAIL);
//	gi.WritePosition (ent->s.origin);
//	gi.WritePosition (temppos);
//	gi.multicast (ent->s.origin, MULTICAST_PHS);

				ent->velocity[0] = 0;
				ent->velocity[1] = 0;
				if(zc->moveyaw == iyaw)
				{
gi.bprintf(PRINT_HIGH,"ladder On!\n");
					ent->s.angles[YAW] = zc->moveyaw;
					VectorCopy(trmax,ent->s.origin);
					zc->zcstate |= STS_LADDERUP; 
					ent->s.angles[YAW] = zc->moveyaw;
					ent->s.angles[PITCH] = -29;

					if(ent->waterlevel > 1)
					{
						ent->velocity[2] = VEL_BOT_WLADRUP;
//				if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
					}
					else
					{
						ent->velocity[2] = VEL_BOT_LADRUP;
//			if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
					}
//					gi.bprintf(PRINT_HIGH,"ladder!!\n");
					goto VCHCANSEL;
				}
				else
				{
					zc->moveyaw = iyaw;
					ent->s.angles[YAW] = zc->moveyaw;
				}
				goto VCHCANSEL;
			}
		}
	}
	
*/
	//--------------------------------------------------------------------------------------
	//rocket jump
	//	ent->client->weaponstate = WEAPON_READY;
	if (ent->groundentity && ent->client->weaponstate == WEAPON_READY && zc->second_target
		&& trace_priority < TRP_ANGLEKEEP)
	{
		if((zc->second_target->s.origin[2] - ent->s.origin[2]) > 100 
			&& ent->health > 70	&& ent->waterlevel <=1 ) 
		{
			j = false;
			v[0] = ent->s.origin[0];
			v[1] = ent->s.origin[1];
			v[2] = zc->second_target->s.origin[2];
			rs_trace = gi.trace(v,NULL,NULL,zc->second_target->s.origin,zc->second_target,MASK_SOLID);
			if(rs_trace.fraction == 1.0) j = true;

			VectorSubtract (zc->second_target->s.origin,ent->s.origin,trmin);
			VectorCopy(trmin,trmax);
			trmax[2] = 0;
			it = Fdi_ROCKETLAUNCHER;//FindItem("Rocket Launcher");
			i = ITEM_INDEX(Fdi_ROCKETS/*FindItem("Rockets")*/);

//ent->client->pers.inventory[ITEM_INDEX(it)] = 1;
//ent->client->pers.inventory[ent->client->ammo_index] = 1;
			if(	VectorLength(trmax) < 280 && canrocj && j)
			{
				VectorNormalize (trmin);
				ent->s.angles[YAW] = Get_yaw (trmin);
				zc->moveyaw = ent->s.angles[YAW];
				ent->s.angles[PITCH] = 90;
				trmin[2] -= 24;
				VectorNormalize (trmin);
//				it->use(ent,it);
				ent->client->pers.weapon = it;
				ent->client->ammo_index = i;
				ShowGun(ent);

				ent->velocity[2] += VEL_BOT_JUMP;
				zc->zcstate |= STS_ROCJ;
				gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
				PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
				Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
				ent->client->buttons |= BUTTON_ATTACK;
				goto VCHCANSEL;		//移動処理キャンセル
			}
			else zc->second_target = NULL;
		}
		else if((zc->second_target->s.origin[2] - ent->s.origin[2]) > 100)
		{
			if(ent->health <= 70 ) zc->second_target = NULL;
		}
	}

	//--------------------------------------------------------------------------------------
	//bot move to moveyaw
GOMOVE:
	//jumping	======================================================
	if(!ent->groundentity && !ent->waterlevel && !ent->client->zc.trapped)
	{
		if(ent->velocity[2] > VEL_BOT_JUMP && !(zc->zcstate & STS_SJMASKEXW)) ent->velocity[2] = VEL_BOT_JUMP;

		k = false;
		if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) k = true;
		for( x = 0 ; x < 90; x += 10)
		{
			dist = MOVE_SPD_RUN * ent->moveinfo.speed;
			//right trace
			yaw = zc->moveyaw + x;
			if(yaw > 180) yaw -= 360;
			i = Bot_moveT(ent,yaw,temppos,dist,&bottom);
			if(i)// true || (i == 2 && ent->velocity > 0))
			{
				if(bottom <= 24 && bottom > 0 && ent->velocity[2] <= 10 /*&& i == true*/)
				{
					//if(ent->velocity[2] > 0 || bottom >= 0)
							VectorCopy(temppos,ent->s.origin);
					break;
				}
				//turbo
				if(!ent->waterlevel && ent->s.origin[2] > ent->s.old_origin[2]
					&& zc->route_trace
					&& !(zc->zcstate & STS_LADDERUP)
					&& !(zc->zcstate & STS_SJMASK)
					&& (zc->routeindex + 1) < CurrentIndex
					&& ent->velocity[2] >= 100 
					&& ent->velocity[2] < (100 + ent->gravity * sv_gravity->value * FRAMETIME))
				{
					Get_RouteOrigin(zc->routeindex ,v);
					Get_RouteOrigin(zc->routeindex + 1,vv);
					k = 0;

					j = Bot_moveT(ent,yaw,trmin,16,&f1);
					VectorSubtract(v,ent->s.origin,trmin);
					if((vv[2] - v[2]) > JumpMax) k = 1;
					else if((v[2] - ent->s.origin[2]) > JumpMax) k = 2;
					else if(!TargetJump_Chk(ent,vv,0) && VectorLength(trmin) < 64)
					{
//gi.bprintf(PRINT_HIGH,"dist %f!!\n",VectorLength(trmin));
						if(TargetJump_Chk(ent,vv,ent->velocity[2])) k = 1;
					}


					if(!j) k = 0;
					else if( f1 > 10 && f1 < -10) k = 0;
					if(k)
					{
						if(k == 2) VectorCopy(v,vv); 
						if(TargetJump_Turbo(ent,vv))
						{
//gi.bprintf(PRINT_HIGH,"speed %f!!\n",ent->moveinfo.speed);
//if(ent->velocity[2] > (VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME ))
//	ent->velocity[2] = VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME;
							VectorSubtract(vv,ent->s.origin,v);
							zc->moveyaw = Get_yaw(v);
							if(ent->velocity[2] > VEL_BOT_JUMP) zc->zcstate |= STS_TURBOJ;
							if(k == 1) zc->routeindex++;
							break;
						}
					}
				}
//				bottom > 0else ent->moveinfo.speed = 0.2;
				if(bottom <= 0)
				{
					VectorCopy(temppos,ent->s.origin);
					if(i == 2 /*&& k*/) ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
					else ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
					break;
				}
				else
				{
					ent->moveinfo.speed = 0.3;//0.2;
				}
			}
			else
			{
				ent->moveinfo.speed = 0.3;//0.2;
			}

			if(x == 0) continue;
			//left trace
			yaw = zc->moveyaw - x;
			if(yaw < -180) yaw += 360;
			i = Bot_moveT(ent,yaw,temppos,dist,&bottom);
			if(i )//== true || (i == 2 && ent->velocity > 0))
			{
				if(bottom <= 24 && bottom >0  && ent->velocity[2] <= 10 /*&& i == true*/)
				{
					//if(ent->velocity[2] > 0 || bottom >= 0)
							VectorCopy(temppos,ent->s.origin);
					break;
				}
				//turbo
				if(!ent->waterlevel && ent->s.origin[2] > ent->s.old_origin[2]
					&& zc->route_trace 
					&& !(zc->zcstate & STS_LADDERUP)
					&& !(zc->zcstate & STS_SJMASK)
					&& (zc->routeindex + 1) < CurrentIndex
					&& ent->velocity[2] >= 100 
					&& ent->velocity[2] < (100 + ent->gravity * sv_gravity->value * FRAMETIME))
				{
					Get_RouteOrigin(zc->routeindex ,v);
					Get_RouteOrigin(zc->routeindex + 1,vv);
					k = 0;

					j = Bot_moveT(ent,yaw,trmin,16,&f1);
					VectorSubtract(v,ent->s.origin,trmin);
					if((vv[2] - v[2]) > JumpMax) k = 1;
					else if((v[2] - ent->s.origin[2]) > JumpMax) k = 2;
					else if(!TargetJump_Chk(ent,vv,0) && VectorLength(trmin) < 64)
					{
//gi.bprintf(PRINT_HIGH,"dist %f!!\n",VectorLength(trmin));
						if(TargetJump_Chk(ent,vv,ent->velocity[2])) k = 1;
					}
					
					if(!j) k = 0;
					else if( f1 > 10 && f1 < -10) k = 0;
					if(k )
					{
						if(k == 2) VectorCopy(v,vv); 
						if(TargetJump_Turbo(ent,vv))
						{
//gi.bprintf(PRINT_HIGH,"speed %f!!\n",ent->moveinfo.speed);
//if(ent->velocity[2] > (VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME ))
//	ent->velocity[2] = VEL_BOT_JUMP + 100 + ent->gravity * sv_gravity->value * FRAMETIME;
//if(ent->moveinfo.speed < 0.5) ent->moveinfo.speed = 0.5;
							VectorSubtract(vv,ent->s.origin,v);
							zc->moveyaw = Get_yaw(v);
							if(ent->velocity[2] > VEL_BOT_JUMP) zc->zcstate |= STS_TURBOJ;
							if(k == 1) zc->routeindex++;
							break;
						}
					}
				}
//				else ent->moveinfo.speed = 0.2;
				if(bottom <= 0)
				{
					VectorCopy(temppos,ent->s.origin);
					if(i == 2 /*&& k*/) ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
					else ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
					break;
				}
				else ent->moveinfo.speed = 0.3;//0.2;
			}
			else ent->moveinfo.speed = 0.3;//0.2;
		}
		if(x >= 90 /*&& ent->velocity[2] < 0*/)
		{
//gi.bprintf(PRINT_HIGH,"jump fail!\n");
			if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] += ((random() - 0.5) * 360);
			if(ent->s.angles[YAW]>180) ent->s.angles[YAW] -= 360;
			else if(ent->s.angles[YAW]< -180) ent->s.angles[YAW] += 360;
		} 
		goto VCHCANSEL;
	}

	// on ground or in water ======================================================
	waterjumped = false;
	if(ent->groundentity || ent->waterlevel )
	{
		if(ent->groundentity && /*zc->waterstate == WAS_NONE*/ent->waterlevel <= 0 ) k = 1;
		else if(ent->waterlevel)
		{
			k = 2;
			if(zc->route_trace)
			{
				Get_RouteOrigin(zc->routeindex,v);
				VectorSubtract(v,ent->s.origin,vv);
				vv[2] = 0;
				if(v[2] < ent->s.origin[2] && VectorLength(vv) < 24) k = 0;
			}
			if(ent->waterlevel == 3) k = 0;
		}
		else if(ent->waterlevel) k = 0;
		else k = 1;
		if(k) if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) k = 0;

		if(zc->waterstate) f1 = BOTTOM_LIMIT_WATER;
		else f1 = - JumpMax;//BOTTOM_LIMIT;//dropable height

		if(zc->nextcheck < (level.time + FRAMETIME * 10))
		{
			VectorSubtract(zc->pold_origin,ent->s.origin,temppos);
			if(VectorLength(temppos) < 64)
			{
				if(zc->route_trace)
				{
					if(!chedit->value)
					{
						zc->route_trace = false;
						zc->routeindex++;
					}
					zc->second_target = NULL;
				}
				else f1 = BOTTOM_LIMITM;
			}

			if(zc->nextcheck < level.time) 
			{
				VectorCopy(ent->s.origin,zc->pold_origin);
				zc->nextcheck = level.time + FRAMETIME * 40;
			}
		}
		f3 = 20;	//movablegap
		//this v not modify till do special
		if(zc->route_trace) Get_RouteOrigin(zc->routeindex,v);

		if(ent->waterlevel && zc->route_trace)
		{
			if(v[2] + 20 <= ent->s.origin[2])
			{
				f2 = 20,f3 = 0;
			}
			else
			{
				if(zc->waterstate /*== WAS_FLOAT*/) f2 = JumpMax;//TOP_LIMIT_WATER;
				else f2 = JumpMax;
			}
		}
		else
		{
			if(zc->waterstate /*== WAS_FLOAT*/) f2 = JumpMax;//TOP_LIMIT_WATER;
			else f2 = JumpMax;
		}

//if(ent->client->ps.pmove.pm_flags & PMF_DUCKED) gi.bprintf(PRINT_HIGH,"cycle!\n");
		ladderdrop = true;
		for( x = 0 ; x <= 180 && dist != 0; x += 10)
		{
			//right trace
			yaw = zc->moveyaw + x;
			if(yaw > 180) yaw -= 360;
			if(j = Bot_moveT (ent,yaw,temppos,dist,&bottom))
			{
				//special
				if(x == 0 && /*bottom < 20 &&*/ !ent->waterlevel
					&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED))
				{
					if( zc->second_target)
					{
						if(((zc->second_target->s.origin[2] + 8 ) - (ent->s.origin[2] + bottom)) > f2)
						{
							if(Bot_Fall(ent,temppos,dist))
							{
								ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
								break;
							}
						}
					}
					else if( zc->route_trace)
					{
//						Get_RouteOrigin(zc->routeindex,v);
//						FRAMETIME * (ent->velocity[2] - ent->gravity * sv_gravity->value * FRAMETIME)
						if((v[2] - (ent->s.origin[2] + bottom )) > f2 ||
							(bottom > 20 && v[2] > ent->s.origin[2]))
						{
							ladderdrop = false;
							if(Bot_Fall(ent,temppos,dist) && !zc->waterstate)
							{
								ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
								break;
							}
							if((v[2] - ent->s.origin[2]) <= JumpMax)
							{
								if(Route[zc->routeindex].state == GRS_ONTRAIN && zc->waterstate < WAS_IN) break;
								if(zc->routeindex > 0) 
									if(Route[zc->routeindex - 1].state == GRS_ONTRAIN
										&& Route[zc->routeindex - 1].ent == ent->groundentity) break;
							}
						}
						else if(ent->groundentity)
						{
//if(Q_stricmp (ent->groundentity->classname,"worldspawn"))
//gi.bprintf(PRINT_HIGH,"%s!\n",ent->groundentity->classname);
							if(!Q_stricmp (ent->groundentity->classname,"func_rotating"))
							{
								if(Bot_Fall(ent,temppos,dist))
								{
									ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
									break;
								}
							}
							else if(Route[zc->routeindex].state == GRS_ONROTATE)
							{
								if(!TraceX(ent,v) || !HazardCheck(ent,v)) break;
								if(!BankCheck(ent,v)) break;
								if(Bot_Fall(ent,temppos,dist))
								{
									ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
									break;
								}
							}
							if(0/*dist < 16 && v[2] < (ent->s.origin[2] - 24) 
								&& !(zc->zcstate & STS_WAITSMASK) && ent->waterlevel*/)
							{
								if(Bot_moveT (ent,yaw,trmin,32,&iyaw))
								{
									if(iyaw < 0)
									{
										ent->moveinfo.speed = 0.05;
										VectorCopy(trmin,ent->s.origin);
										break;
									}
								}	
							}
						}
					}
				}
				
				//jumpable1
				if(/*((bottom > 20 && !ent->waterlevel) || (bottom > 0 && (ent->waterlevel == 2 || (ent->waterlevel == 1 && ent->groundentity == NULL))))*/
					bottom > 20
					&& bottom <= f2 && j == true && k
					&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED))
				{
					ent->moveinfo.speed = 0.15;
					if(k == 1/*!ent->waterlevel*/)
					{
						ent->velocity[2] += VEL_BOT_JUMP;
						gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
					}
					else
					{
						ent->moveinfo.speed = 0.1;
						//waterjumped = true;
						if(ent->velocity[2] < VEL_BOT_WJUMP/*=1*/ || VectorCompare(ent->s.origin,ent->s.old_origin))
						{
							ent->velocity[2] /*+*/= VEL_BOT_WJUMP;//(/*VEL_BOT_WJUMP*/ 110 /*+ bottom*/);
							zc->zcstate |= STS_WATERJ;
							goto VCHCANSEL;
						}
						goto VCHCANSEL;
					}
					Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
					zc->moveyaw = yaw;
					ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
					break;
				}
				//dropable1
				else if(bottom <= f3 &&(bottom >= f1 || /*zc->waterstate*/ent->waterlevel /* 2*/)) 
				{
//					ent->client->anim_priority = ANIM_BASIC;
					if(bottom < 0 && !zc->waterstate/*(ent->waterlevel && !zc->waterstate/*ent->waterlevel < 2)*/)
					{
						f2 = FRAMETIME * (ent->velocity[2] - ent->gravity * sv_gravity->value * FRAMETIME);
						if(bottom >= f2 && ent->velocity[2] < 0/*20*/) temppos[2] += bottom;
						else temppos[2] += f2;//20;
					}		
					VectorCopy(temppos,ent->s.origin);
					if(f1 > BOTTOM_LIMIT) ent->moveinfo.speed = 0.25;
					if(j != true)
					{
//gi.bprintf(PRINT_HIGH,"ducked1!!\n");
						ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
					}
					else ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;

					if(x > 30 || !zc->route_trace)
					{
						f2 = zc->moveyaw;
						zc->moveyaw = yaw;
						if(f2 == ent->s.angles[YAW] && trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = yaw;
					}
					break;
				}
				//dropable?1
				else if ( bottom < f1 && !zc->waterstate/*!ent->waterlevel*/ && x <= 30)
				{
					if( ladderdrop &&  zc->ground_contents & CONTENTS_LADDER && bottom != -9999) 
					{
						VectorCopy(temppos,ent->s.origin);
						zc->moveyaw = yaw;
						ent->moveinfo.speed = 0.2;
						goto VCHCANSEL;
					}

					if( ladderdrop &&  bottom < 0 && !zc->waterstate/*!ent->waterlevel*/)
					{
						if(Bot_moveW ( ent,yaw,temppos,dist,&bottom))
						{
							if(zc->second_target) iyaw = zc->second_target->s.origin[2] - ent->s.origin[2];
							else iyaw = -41;
							if(bottom > -20 && iyaw < -40)
							{
								VectorCopy(temppos,ent->s.origin);
								break;
							}
						}
					}
					//fall1
					if(Bot_Fall(ent,temppos,dist))
					{
//						ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
//gi.bprintf(PRINT_HIGH,"drop!\n");
						break;
					}
				}
			}
//else if(ent->client->zc.waterstate == 1 && x == 0) gi.bprintf(PRINT_HIGH,"maaaap %i\n",j);

			if(x == 0 && (zc->battlemode & FIRE_SHIFT)) zc->battlemode &= ~FIRE_SHIFT;
			if(x == 0 || x == 180) continue;
			//left trace
			yaw = zc->moveyaw - x;
			if(yaw < -180) yaw += 360;
			if(j = Bot_moveT (ent,yaw,temppos,dist,&bottom))
			{
				if(zc->waterstate == WAS_FLOAT) f2 = TOP_LIMIT_WATER;
				else f2 = JumpMax;
				//jumpable2
				if(/*((bottom > 20 && !ent->waterlevel) || (bottom > 0 && (ent->waterlevel == 2 || (ent->waterlevel == 1 && ent->groundentity == NULL))) )*/
					bottom > 20
					&& bottom <= f2 && j == true && k
					&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED))
				{
					ent->moveinfo.speed = 0.15;
					if(k == 1/*!ent->waterlevel*/)
					{
						ent->velocity[2] += VEL_BOT_JUMP;
						gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
					}
					else
					{
						ent->moveinfo.speed = 0.1;
						//waterjumped = true;
						if(ent->velocity[2] < VEL_BOT_WJUMP/*= 1*/ || VectorCompare(ent->s.origin,ent->s.old_origin))
						{
							ent->velocity[2] /*+*/= VEL_BOT_WJUMP;//(/*VEL_BOT_WJUMP*/ 110 /*+ bottom*/);
							zc->zcstate |= STS_WATERJ;
							goto VCHCANSEL;
						}
						goto VCHCANSEL;
					}
					Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
					zc->moveyaw = yaw;
					ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
					break;
				}
				//dropable2
				else if(bottom <= f3 && (bottom >= f1 || ent->waterlevel /* 2zc->waterstate*/)) 
				{
					//ent->client->anim_priority = ANIM_BASIC;
					if(bottom < 0 && !zc->waterstate/*(ent->waterlevel && !zc->waterstate/*ent->waterlevel < 2)*/)
					{					
//gi.bprintf(PRINT_HIGH,"ponko\n");
						f2 = FRAMETIME * (ent->velocity[2] - ent->gravity * sv_gravity->value * FRAMETIME);
						if(bottom >= f2 && ent->velocity[2] < 0/*20*/) temppos[2] += bottom;
						else temppos[2] += f2;//20;
					}		
					VectorCopy(temppos,ent->s.origin);
					if(f1 > BOTTOM_LIMIT) ent->moveinfo.speed = 0.25;
					if(j != true)
					{
//gi.bprintf(PRINT_HIGH,"ducked2!!\n");
						ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
					}
					else ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
					
					if(x > 30 || !zc->route_trace)
					{
						f2 = zc->moveyaw;
						zc->moveyaw = yaw;
						if(f2 == ent->s.angles[YAW]  && trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = yaw;
					}
					break;
				}
				//dropable?2
				else if (bottom < f1 && !zc->waterstate/*!ent->waterlevel*/ && x <= 30)
				{
					if( ladderdrop && zc->ground_contents & CONTENTS_LADDER  && bottom != -9999) 
					{
						VectorCopy(temppos,ent->s.origin);
						zc->moveyaw = yaw;
						ent->moveinfo.speed = 0.2;
						goto VCHCANSEL;
					}

					if( ladderdrop && bottom < 0 && !zc->waterstate/*!ent->waterlevel*/)
					{
						if(Bot_moveW ( ent,yaw,temppos,dist,&bottom))
						{
							if(zc->second_target) iyaw = zc->second_target->s.origin[2] - ent->s.origin[2];
							else iyaw = -41;
							if(bottom > -54 && iyaw < -40)
							{
								VectorCopy(temppos,ent->s.origin);
								break;
							}
						}
					}

					//fall2
					if(Bot_Fall(ent,temppos,dist))
					{
//						ent->client->ps.pmove.pm_flags &= ~PMF_DUCKED;
						break;
					}
				}
			}
		}

		if(!zc->route_trace && zc->first_target == NULL)
		{
			if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = yaw;
		}

		if(x >= 70)
		{
			if(zc->second_target) zc->second_target = NULL;
/*			else if(!zc->route_trace && zc->first_target == NULL)
			{
				if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = yaw;
			}*/
			else if( 0/*zc->route_trace*/)
			{
//gi.bprintf(PRINT_HIGH,"OFF 9\n"); //ppx
				k = false;
				if(  x > 90 && ent->groundentity)
				{
					if(!Q_stricmp (ent->groundentity->classname,"func_train")) k = true;
				}
				else if( x > 90 && Route[zc->routeindex].state == GRS_ONTRAIN) k = true;
				if(k && trace_priority < TRP_ANGLEKEEP) 
				{
					VectorCopy(Origin,ent->s.origin);
					VectorCopy(Velocity,ent->velocity);
					ent->s.angles[YAW] = OYaw;
					goto VCHCANSEL;
				}
/*				if(!k)
				{
					if(++zc->routeindex >= CurrentIndex) zc->routeindex = 0;
					zc->route_trace = false;
				}*/
			}
		}

		if(/*zc->waterstate*/ent->waterlevel && !waterjumped)
		{
			k = false;
			VectorCopy(ent->s.origin,temppos);
//			temppos[2] += 26;
//			i = gi.pointcontents (temppos);
			if(zc->second_target != NULL)
			{
				k = 2;
				x = zc->second_target->s.origin[2] - ent->s.origin[2];
				if(x > 13/*8*/) x = 13;//8;
				else if(x < -13/*8*/) x = -13;//8;
				if(x < 0)//アイテム下方
				{
					if( Bot_Watermove (ent,temppos,dist,x))
					{
						VectorCopy(temppos,ent->s.origin);
						k = true;
					}
				}
				else if(x >0 && zc->waterstate == WAS_IN
					&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED)) //アイテム上方
				{
					if(ent->velocity[2] < 0) ent->velocity[2] = 0; 
					if( Bot_Watermove (ent,temppos,dist,x))
					{
						VectorCopy(temppos,ent->s.origin);
						k = true;
					}
				}
			}
			else if(zc->route_trace )
			{
				Get_RouteOrigin(zc->routeindex,v);

				k = 2;
				x = v[2] - ent->s.origin[2];
				if(x > 13/*8*/) x = 13;//8;
				else if(x < -13/*8*/) x = -13;//8;
				if(x < 0)//アイテム下方
				{
					if( Bot_Watermove (ent,temppos,dist,x))
					{
//gi.bprintf(PRINT_HIGH,"Down! %f\n",x);
						VectorCopy(temppos,ent->s.origin);
						k = true;
					}
				}
				else if(x > 0 && zc->waterstate == WAS_IN
					&& !(ent->client->ps.pmove.pm_flags & PMF_DUCKED)) //アイテム上方
				{
//gi.bprintf(PRINT_HIGH,"UP! %f\n",x);
					if(ent->velocity[2] < -10) ent->velocity[2] = 0; 
					if( Bot_Watermove (ent,temppos,dist,x))
					{
						VectorCopy(temppos,ent->s.origin);
						k = true;
					}
				}
				else if(x == 0)
				{
//gi.bprintf(PRINT_HIGH,"ZERO! %f\n",x);
//					VectorSubtract(v,ent->s.origin,vv);
//					if(VectorLength(vv) < 13) VectorCopy(v,ent->s.origin);
				}
			}
			else if((ent->air_finished - FRAMETIME * 20 ) < level.time
				&& zc->waterstate == WAS_IN)
			{
				if( Bot_Watermove (ent,temppos,dist,13/*8*/))
				{
					VectorCopy(temppos,ent->s.origin);
					k = true;
				}
				else k = 2;
			}

			if(k == true) Get_WaterState(ent);
			if(zc->route_trace && v[2] == ent->s.origin[2]) k = 3;

			if((!ent->groundentity && !zc->waterstate && k && ent->velocity[2] < 1)
				||(zc->waterstate == WAS_IN && (ent->client->ps.pmove.pm_flags & PMF_DUCKED)))
			{
				if( Bot_Watermove (ent,temppos,dist,-7/*8*/) && k != 3)
				{
					VectorCopy(temppos,ent->s.origin);
				}				
			}
			if(zc->waterstate == WAS_IN)  ent->moveinfo.decel = level.time;
			else if(!k)	//水面にずっといたとき
			{
				if( ( level.time - ent->moveinfo.decel) > 4.0 && !zc->route_trace)
				{
					ent->velocity[2] = -200;
					ent->moveinfo.decel = level.time;
				}
			}

			if(ent->groundentity && ent->waterlevel == 1)
			{
				VectorSubtract(ent->s.origin,ent->s.old_origin,temppos);
				if(!temppos[0] && !temppos[1] && !temppos[2]) ent->velocity[2] += 80;
			} 
		}
		//not in water
		else if(zc->route_trace && !dist)
		{
			Get_RouteOrigin(zc->routeindex,v);
			if(v[2] < (ent->s.origin[2] - 20))
			{
				if( Bot_Watermove (ent,temppos,dist,-20))
				{
					VectorCopy(temppos,ent->s.origin);
				}
			}
		}

	}
	//sticking
/*	if(VectorCompare(ent->s.origin,ent->s.old_origin) && ent->waterlevel)
	{
		ent->velocity[2] += 200;
	}
*/
	//--------------------------------------------------------------------------------------
	//player check door and corner
	if(!zc->route_trace && trace_priority && !zc->second_target && random() < 0.2)
	{
		VectorCopy(ent->s.origin,v);
		VectorCopy(ent->mins,touchmin);
		touchmin[2] += 16;
		VectorCopy(ent->maxs,touchmax);
		if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)	touchmax[2] = 0;
		else v[2] += 20;

		//right
		if(random() < 0.5)
		{
			f1 = zc->moveyaw + 90;
			if(f1 > 180) iyaw -= 360;
			f2 = zc->moveyaw + 135;
			if(f2 > 180) iyaw -= 360;
		}
		//left
		else
		{
			f1 = zc->moveyaw - 90;
			if(f1 < 180) iyaw += 360;
			f2 = zc->moveyaw - 135;
			if(f2 < 180) iyaw += 360;
		}

		yaw = f1 * M_PI * 2 / 360;
		trmin[0] = cos(yaw) * 128 ;
		trmin[1] = sin(yaw) * 128 ;
		trmin[2] = 0;
		VectorAdd(v,trmin,trmax);
		rs_trace = gi.trace (v, NULL,NULL, trmax,ent, MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/ );
		x = rs_trace.fraction;

		yaw = f2 * M_PI * 2 / 360;
		trmin[0] = cos(yaw) * 128 ;
		trmin[1] = sin(yaw) * 128 ;
		trmin[2] = 0;
		VectorAdd(v,trmin,trmax);
		rs_trace = gi.trace (v, NULL/*touchmin*/,NULL/*touchmax*/, trmax,ent, MASK_BOTSOLIDX/*MASK_PLAYERSOLID*/ );		
		
		if( x > rs_trace.fraction && x > 0.5) zc->moveyaw = f1;
	}


	//--------------------------------------------------------------------------------------
	//push button

	it_ent = NULL;
	k = 0;

	VectorCopy (ent->absmin, touchmin);
	VectorCopy (ent->absmax, touchmax);

	touchmin[0] -= 48;//32;
	touchmin[1] -= 48;//32;
	touchmin[2] -= 5;
	touchmax[0] += 48;//32;
	touchmax[1] += 48;//32;
	i = gi.BoxEdicts ( touchmin ,touchmax,touch,MAX_EDICTS,AREA_SOLID);

	if(i)
	{
		for(j = i - 1;j >= 0;j--)
		{
			trent = touch[j]; 
			if(trent->classname)
			{
				if(!Q_stricmp (trent->classname,"func_button"))
				{
					k = 1;
					it_ent = trent;
					break;
				}
				else if(!Q_stricmp (trent->classname,"func_door")
					|| !Q_stricmp (trent->classname,"func_door_rotating"))
				{
					if(trent->targetname == NULL && !trent->takedamage && ent->groundentity != trent)
					{
						k = 2;
						it_ent = trent;
						break;
					}
				}
			}
		}
	}
	//when touch da button
	if( it_ent != NULL && k == 1)
	{
		if(it_ent->use && it_ent->moveinfo.state == PSTATE_BOTTOM && !it_ent->health)
		{
			k = false;
			if(zc->route_trace && zc->routeindex - 1 > 0)
			{
				k = true;
				i = zc->routeindex;
				if(Route[i].state == GRS_PUSHBUTTON) k = false;
				else if(Route[--i].state == GRS_PUSHBUTTON) k = false;

				if(!k && Route[i].ent == it_ent) zc->routeindex = i + 1;
				else k = true;
			}
			
//			if(!k) buttonuse = true;//it_ent->use(it_ent,ent,it_ent/*ent*/);
			if(!k && it_ent->target)
			{
				string = it_ent->target;
				e = &g_edicts[(int)maxclients->value+1];
				for ( i=maxclients->value+1 ; i<globals.num_edicts ; i++, e++)
				{
					if(!e->inuse || !e->targetname) continue;
					if (Q_stricmp (string, e->targetname) == 0 )
					{
//gi.bprintf(PRINT_HIGH,"yea4  %i %s\n",e->moveinfo.state,e->classname);
						if(e->classname[0] == 't')
						{
							if(!Q_stricmp (e->classname,"trigger_relay"))
							{
								if(e->target)
								{
									string = e->target;
									e = &g_edicts[(int)maxclients->value];
									i=maxclients->value;
									continue;
								}
							}
							else if(!Q_stricmp (e->classname,"target_laser")
								|| !Q_stricmp (e->classname,"target_mal_laser"))
							{
								if(e->spawnflags & 1)
								{
									it_ent->use(it_ent,ent,it_ent);
									break;
								}
							}
						}
						else if(e->classname[0] == 'f')
						{
							it_ent->use(it_ent,ent,it_ent/*ent*/);
							if(!Q_stricmp (e->classname,"func_door") 
								|| !Q_stricmp ( e->classname,"func_door_rotating")
								/*&& (e->moveinfo.state == 1 || e->moveinfo.state == 2)*/
							)//	&& abs ((e->moveinfo.start_origin[2] - e->moveinfo.end_origin[2])) > 54 )
							{
								k = false;
	//							return true;
								if(!zc->route_trace /*|| zc->routeindex <= 0*/)
								{
									v[0] = (it_ent->absmin[0] + it_ent->absmax[0]) / 2;
									v[1] = (it_ent->absmin[1] + it_ent->absmax[1]) / 2;
									v[2] = (it_ent->absmin[2] + it_ent->absmax[2]) / 2;
									VectorSubtract(it_ent->union_ent->s.origin,v,temppos);
									VectorScale (temppos, 3, v);
									VectorAdd(ent->s.origin,v,zc->movtarget_pt);
								}
								else
								{
									/*Get_RouteOrigin(zc->routeindex - 1,v);
									VectorSubtract(v,ent->s.origin,temppos);
									VectorScale (temppos, 3, v);
									VectorCopy(ent->s.origin,temppos);
									VectorAdd(ent->s.origin,v,zc->movtarget_pt);*/
									VectorCopy(ent->s.origin,zc->movtarget_pt);
								}
								//VectorScale (temppos, 3, v);
								//VectorAdd(ent->s.origin,v,zc->movtarget_pt);
	
								if(fabs (e->moveinfo.start_origin[2] - e->moveinfo.end_origin[2]) > JumpMax )
								{
									if(e->union_ent == NULL)
									{
//gi.bprintf(PRINT_HIGH,"voodoo\n"); //ppx
										it = FindItem("Roam Navi3");
										trent = G_Spawn();
										trent->classname = it->classname;
										trent->s.origin[0] = (e->absmin[0] + e->absmax[0])/2;
										trent->s.origin[1] = (e->absmin[1] + e->absmax[1])/2;
										trent->s.origin[2] = e->absmax[2] + 16;
										trent->union_ent = e;
										e->union_ent = trent;

										//trent->nextthink = level.time + 10;
										//trent->think = G_FreeEdict;

										SpawnItem3 (trent, it);
									}
									else
									{
										trent = e->union_ent;
										trent->solid = SOLID_TRIGGER;
										trent->svflags &= ~SVF_NOCLIENT;
//gi.bprintf(PRINT_HIGH,"SPAWNed\n"); //ppx
									}
//									SpawnItem2 (trent, it);
	
									zc->second_target = trent;
									trent->target_ent = ent;

									//トグル式はすぐ走る
									if(e->spawnflags & PDOOR_TOGGLE)
									{
										f1 = e->moveinfo.start_origin[2] - e->moveinfo.end_origin[2];
										//スタート地点が上
										if(f1 > 0 )
										{
											k = true;
											if(e->moveinfo.state == PSTATE_BOTTOM || e->moveinfo.state == PSTATE_UP )
											{
												if((trent->s.origin[2] - ent->s.origin[2]) > 32) zc->second_target = NULL;
											}
											else if(e->moveinfo.state == PSTATE_TOP || e->moveinfo.state == PSTATE_DOWN)
											{
												if((trent->s.origin[2] - ent->s.origin[2]) < -48) zc->second_target = NULL;
											}
										}
										else
										{
											k = true;
											if(e->moveinfo.state == PSTATE_TOP || e->moveinfo.state == PSTATE_DOWN)
											{
												if((trent->s.origin[2] - ent->s.origin[2]) > 32) zc->second_target = NULL;
											}
											else if(e->moveinfo.state == PSTATE_BOTTOM || e->moveinfo.state == PSTATE_UP)
											{
												if((trent->s.origin[2] - ent->s.origin[2]) < -48) zc->second_target = NULL;
											}
										}
									}
									//ノーマル
									else
									{
										f1 = e->moveinfo.start_origin[2] - e->moveinfo.end_origin[2];
										//スタート地点が上
										if(f1 > 0 )
										{
											if(e->moveinfo.state == PSTATE_BOTTOM || e->moveinfo.state == PSTATE_UP)
											{
												if(fabs(trent->s.origin[2] - ent->s.origin[2]) < JumpMax) k = true; 
											}
										}
										else
										{
											if(e->moveinfo.state == PSTATE_BOTTOM || e->moveinfo.state == PSTATE_UP )
											{
												if(fabs(trent->s.origin[2] - ent->s.origin[2]) < JumpMax) k = true;
											}
										}
									}
//									if(Bot_trace (ent,zc->second_target)) k = true;
								}
								if(!k)
								{
									//gi.bprintf(PRINT_HIGH,"waitset %i\n",e->moveinfo.state);
									zc->waitin_obj = e;
									zc->zcstate &= ~STS_WAITS;
									zc->zcstate |= STS_W_DOOROPEN;	
								}
								else
								{
									if((e->union_ent->s.origin[2] + 8
											- ent->s.origin[2]) > JumpMax)
									{
										zc->route_trace = false;
										zc->zcstate &= ~STS_WAITS;
									}
								}
								break;
							}
						}
					}			
				}
			}
			else if(!k) it_ent->use(it_ent,ent,it_ent/*ent*/);
		}
		
	}
	//when touch da door
	else if( it_ent != NULL && k == 2)
	{
		if(it_ent->moveinfo.state == PSTATE_BOTTOM)
		{
			if(it_ent->flags & FL_TEAMSLAVE)  it_ent->teammaster->use(it_ent->teammaster,ent,it_ent->teammaster/*ent*/);
			else it_ent->use(it_ent,ent,it_ent/*ent*/);
		}

//if(zc->zcstate & STS_WAITSMASK ) gi.bprintf(PRINT_HIGH,"Door Use\n");		

		if(it_ent->moveinfo.state == PSTATE_BOTTOM)
		{
			VectorCopy(ent->s.origin,zc->movtarget_pt);
			zc->waitin_obj = it_ent;
			zc->zcstate &= ~STS_WAITS;
			zc->zcstate |= STS_W_DOOROPEN;	

			if(it_ent->flags & FL_TEAMSLAVE)
			{
				trmin[0] = (it_ent->teammaster->absmin[0] + it_ent->teammaster->absmax[0]) / 2;
				trmin[1] = (it_ent->teammaster->absmin[1] + it_ent->teammaster->absmax[1]) / 2;
				trmax[0] = (it_ent->absmin[0] + it_ent->absmax[0]) / 2;
				trmax[1] = (it_ent->absmin[1] + it_ent->absmax[1]) / 2;				

				temppos[0] = (trmin[0] + trmax[0]) /2;
				temppos[1] = (trmin[1] + trmax[1]) /2;
				if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = Get_yaw(temppos);	
			}
			else 
			{
				trmax[0] = (it_ent->absmin[0] + it_ent->absmax[0]) / 2;
				trmax[1] = (it_ent->absmin[1] + it_ent->absmax[1]) / 2;	
				VectorSubtract(trmax,ent->s.origin,temppos);
				if(trace_priority < TRP_ANGLEKEEP) ent->s.angles[YAW] = Get_yaw(temppos);			
			}
		}
		else if(it_ent->moveinfo.state == PSTATE_UP )
		{
			VectorCopy(ent->s.origin,zc->movtarget_pt);
			zc->waitin_obj = it_ent;
			zc->zcstate &= ~STS_WAITS;
			zc->zcstate |= STS_W_DOOROPEN;	
		}
	}
VCHCANSEL:
	//--------------------------------------------------------------------------------------
	//ladder check
	front = NULL, left = NULL, right = NULL;
	k = false;
	if(zc->route_trace && (zc->routeindex + 1) < CurrentIndex)
	{
		Get_RouteOrigin(zc->routeindex + 1,v);
		if((v[2] - ent->s.origin[2]) >= 32 /*|| ent->waterlevel*/) k = true;
	}
	if(k && trace_priority && !zc->second_target && !(ent->client->ps.pmove.pm_flags & PMF_DUCKED))
	{
		tempflag = false;

		VectorCopy(ent->mins,trmin);
		VectorCopy(ent->maxs,trmax);

		trmin[2] += 20;

		//front
		f1 = 32;
		if(zc->route_trace) f1 = 32;

		iyaw = zc->moveyaw;
		yaw = iyaw * M_PI * 2 / 360;
		touchmin[0] = cos(yaw) * f1;//28 ;
		touchmin[1] = sin(yaw) * f1;
		touchmin[2] = 0;

		VectorAdd(ent->s.origin,touchmin,touchmax);
		rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID );
		front = rs_trace.ent;

		if(rs_trace.contents & CONTENTS_LADDER) tempflag = true;

		//upper
		if(!tempflag && !zc->waterstate)
		{		
			trmax[2] += 32;
			rs_trace = gi.trace (ent->s.origin, trmin,trmax, touchmax,ent, MASK_BOTSOLID );
			if(rs_trace.contents & CONTENTS_LADDER) tempflag = 2;
		}
		if(!tempflag && ent->groundentity)
		{
			Get_RouteOrigin(zc->routeindex,v);
			v[2] = ent->s.origin[2];//0;
			rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, v,ent, MASK_BOTSOLID );
			if(rs_trace.contents & CONTENTS_LADDER) tempflag = 3;
		}

		//right
		if(!tempflag)
		{
			iyaw = zc->moveyaw + 90;
			if(iyaw > 180) iyaw -= 360;
			yaw = iyaw * M_PI * 2 / 360;
			touchmin[0] = cos(yaw) * 32 ;
			touchmin[1] = sin(yaw) * 32 ;
			touchmin[2] = 0;

			VectorAdd(ent->s.origin,touchmin,touchmax);
			rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent,  MASK_BOTSOLID );
			right = rs_trace.ent;

			if(rs_trace.contents & CONTENTS_LADDER) tempflag = true;
		}
		//left
		if(!tempflag)
		{
			iyaw = zc->moveyaw - 90;
			if(iyaw < -180) iyaw += 360;
			yaw = iyaw * M_PI * 2 / 360;
			touchmin[0] = cos(yaw) * 32 ;
			touchmin[1] = sin(yaw) * 32 ;
			touchmin[2] = 0;

			VectorAdd(ent->s.origin,touchmin,touchmax);
			rs_trace = gi.trace (ent->s.origin, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID );
			left = rs_trace.ent;

			if(rs_trace.contents & CONTENTS_LADDER)	tempflag = true;
		}

		//ladder
		if(tempflag)
		{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"ladder founded! %f\n",iyaw);
#endif
			VectorCopy(rs_trace.endpos,trmax);
			VectorCopy(trmax,touchmax);
			touchmax[2] += 8190;
			rs_trace = gi.trace (/*temppos*/trmax, trmin,ent->maxs, touchmax,ent, MASK_SOLID );

			 e = rs_trace.ent;
//if((rs_trace.contents & CONTENTS_LADDER)) gi.bprintf(PRINT_HIGH,"damn!\n");

			k = 0;
			VectorCopy(rs_trace.endpos,temppos);
			VectorAdd(rs_trace.endpos,touchmin,touchmax);
			rs_trace = gi.trace (temppos, trmin,ent->maxs, touchmax,ent, MASK_BOTSOLID);
			
			if(e)
			{
				if(Q_stricmp (e->classname, "func_door") == 0)
				{
					k = true;
				}
			}

			if((!(rs_trace.contents & CONTENTS_LADDER) || k) /*&& rs_trace.fraction < 1.0*/)
			{
//	gi.WriteByte (svc_temp_entity);
//	gi.WriteByte (TE_RAILTRAIL);
//	gi.WritePosition (ent->s.origin);
//	gi.WritePosition (temppos);
//	gi.multicast (ent->s.origin, MULTICAST_PHS);

				ent->velocity[0] = 0;
				ent->velocity[1] = 0;
				if(zc->moveyaw == iyaw || zc->route_trace)
				{
#ifdef _DEBUG
gi.bprintf(PRINT_HIGH,"ladder On!\n");
#endif
					
/*					x = Get_yaw(rs_trace.plane.normal);
					x += 180;
					if(x > 180) x -= 360;
					zc->moveyaw = x;*/
					if(zc->moveyaw != iyaw)  zc->moveyaw = iyaw;

					ent->s.angles[YAW] = zc->moveyaw;
					if(tempflag != 3) VectorCopy(trmax,ent->s.origin);
					zc->zcstate |= STS_LADDERUP; 
					ent->s.angles[YAW] = zc->moveyaw;
					ent->s.angles[PITCH] = -29;

					if(tempflag == 2)
					{
						ent->velocity[2] += VEL_BOT_JUMP;
						gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
						Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
						zc->zcstate |= STS_SJMASK;
//						ent->s.frame = FRAME_jump1-1;
//						ent->client->anim_end = FRAME_jump6;
//						ent->client->anim_priority = ANIM_JUMP;
						ent->moveinfo.speed = 0;
					}
					else if(tempflag == 3)
					{
						ent->velocity[2] += VEL_BOT_JUMP;
						gi.sound(ent, CHAN_VOICE, gi.soundindex("*jump1.wav"), 1, ATTN_NORM, 0);
						PlayerNoise(ent, ent->s.origin, PNOISE_SELF);	//pon
						Set_BotAnim(ent,ANIM_JUMP,FRAME_jump1-1,FRAME_jump6);
						zc->zcstate |= STS_SJMASK;
//						ent->s.frame = FRAME_jump1-1;
//						ent->client->anim_end = FRAME_jump6;
//						ent->client->anim_priority = ANIM_JUMP;
						ent->moveinfo.speed = MOVE_SPD_JUMP;
					}
					else if(ent->waterlevel > 1)
					{
						ent->velocity[2] = VEL_BOT_WLADRUP;
//				if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
					}
					else
					{
						ent->velocity[2] = VEL_BOT_LADRUP;
//			if(VectorCompare(ent->s.origin,ent->s.old_origin)) ent->velocity[2] += 50;
					}
//					gi.bprintf(PRINT_HIGH,"ladder!!\n");
//					goto VCHCANSEL;
				}
				else
				{
					zc->moveyaw = iyaw;
					ent->s.angles[YAW] = zc->moveyaw;
				}
//				goto VCHCANSEL;
			}
		}
	}
VCHCANSEL_L:	
	//--------------------------------------------------------------------------------------
	//player sizebox set
	// ducked
	//special duckset
	if(ent->client->zc.battleduckcnt > 0 && ent->groundentity && ent->velocity[2] < 10)
	{
		ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
		ent->client->zc.battleduckcnt--;
	}

	if(ent->client->ps.pmove.pm_flags & PMF_DUCKED)
	{
		ent->client->zc.n_duckedtime = 0;
		ent->maxs[2] = 4;
		ent->viewheight = -2;
	}
	// not ducked
	else
	{
		if(ent->client->zc.n_duckedtime < FRAMETIME * 10) ent->client->zc.n_duckedtime += FRAMETIME;
		ent->maxs[2] = 32;
		ent->viewheight = 22;
	}

	//--------------------------------------------------------------------------------------
	// angle set
	VectorCopy(ent->s.angles,ent->client->v_angle);
	if(ent->s.angles[PITCH] < -29) ent->s.angles[PITCH] = -29;
	else if(ent->s.angles[PITCH] > 29) ent->s.angles[PITCH] = 29;
	
	//--------------------------------------------------------------------------------------

//ZOID
	if (ent->client->ctf_grapple)
	{
/*		if(ent->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY)
		{
			if(ent->waterlevel && !waterjumped) VectorClear(ent->velocity);
		}*/
		CTFGrapplePull(ent->client->ctf_grapple);
		if(ent->client->ctf_grapplestate > CTF_GRAPPLE_STATE_FLY)
		{
			e = (edict_t*)ent->client->ctf_grapple;
			//ent->velocity[2] =  ent->gravity * sv_gravity->value * FRAMETIME;
			if(ent->groundentity && ent->velocity[2] < 0) ent->velocity[2] =  ent->gravity * sv_gravity->value * FRAMETIME;
			else if(VectorCompare(ent->s.origin,ent->s.old_origin))
			{
				ent->velocity[2] +=  JumpMax;//ent->gravity * sv_gravity->value * FRAMETIME * 4;

				if(ent->client->ctf_grapplestate == CTF_GRAPPLE_STATE_PULL)
				{
					VectorSubtract(ent->s.origin,e->s.origin,v);
					yaw = Get_yaw(v);
					
					yaw = yaw * M_PI * 2 / 360;
					ent->velocity[0] += cos(yaw) * 200 ;				//start
					ent->velocity[1] += sin(yaw) * 200 ;
				}
			}
			else ent->velocity[2] +=  ent->gravity * sv_gravity->value * FRAMETIME * 2;
		}
	}
	else
	{
		if(ent->waterlevel > 2) {ent->velocity[0] = 0;ent->velocity[1] = 0;/*VectorClear(ent->velocity);*/}
		else if(ent->waterlevel && !ent->groundentity && ent->velocity[2] < 0) VectorClear(ent->velocity);//ent->velocity[2] = 0; 
	}
//ZOID

/*
ent->velocity[0] = 800 * (random() - 0.5);
ent->velocity[1] = 800 * (random() - 0.5);

ent->client->ps.pmove.pm_flags |= PMF_DUCKED;
*/
	ent->client->zc.trapped = false;		//trapcatch clear

	gi.linkentity (ent);
	G_TouchTriggers (ent);
}
