亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關(guān)于我們
? 蟲蟲下載站

?? g_ai.c

?? 著名游戲quake2原代碼最新版本(vc6.0可以編譯的)
?? C
?? 第 1 頁(yè) / 共 2 頁(yè)
字號(hào):
/*
Copyright (C) 1997-2001 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// g_ai.c

#include "g_local.h"

qboolean FindTarget (edict_t *self);
extern cvar_t	*maxclients;

qboolean ai_checkattack (edict_t *self, float dist);

qboolean	enemy_vis;
qboolean	enemy_infront;
int			enemy_range;
float		enemy_yaw;

//============================================================================


/*
=================
AI_SetSightClient

Called once each frame to set level.sight_client to the
player to be checked for in findtarget.

If all clients are either dead or in notarget, sight_client
will be null.

In coop games, sight_client will cycle between the clients.
=================
*/
void AI_SetSightClient (void)
{
	edict_t	*ent;
	int		start, check;

	if (level.sight_client == NULL)
		start = 1;
	else
		start = level.sight_client - g_edicts;

	check = start;
	while (1)
	{
		check++;
		if (check > game.maxclients)
			check = 1;
		ent = &g_edicts[check];
		if (ent->inuse
			&& ent->health > 0
			&& !(ent->flags & FL_NOTARGET) )
		{
			level.sight_client = ent;
			return;		// got one
		}
		if (check == start)
		{
			level.sight_client = NULL;
			return;		// nobody to see
		}
	}
}

//============================================================================

/*
=============
ai_move

Move the specified distance at current facing.
This replaces the QC functions: ai_forward, ai_back, ai_pain, and ai_painforward
==============
*/
void ai_move (edict_t *self, float dist)
{
	M_walkmove (self, self->s.angles[YAW], dist);
}


/*
=============
ai_stand

Used for standing around and looking for players
Distance is for slight position adjustments needed by the animations
==============
*/
void ai_stand (edict_t *self, float dist)
{
	vec3_t	v;

	if (dist)
		M_walkmove (self, self->s.angles[YAW], dist);

	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
	{
		if (self->enemy)
		{
			VectorSubtract (self->enemy->s.origin, self->s.origin, v);
			self->ideal_yaw = vectoyaw(v);
			if (self->s.angles[YAW] != self->ideal_yaw && self->monsterinfo.aiflags & AI_TEMP_STAND_GROUND)
			{
				self->monsterinfo.aiflags &= ~(AI_STAND_GROUND | AI_TEMP_STAND_GROUND);
				self->monsterinfo.run (self);
			}
			M_ChangeYaw (self);
			ai_checkattack (self, 0);
		}
		else
			FindTarget (self);
		return;
	}

	if (FindTarget (self))
		return;
	
	if (level.time > self->monsterinfo.pausetime)
	{
		self->monsterinfo.walk (self);
		return;
	}

	if (!(self->spawnflags & 1) && (self->monsterinfo.idle) && (level.time > self->monsterinfo.idle_time))
	{
		if (self->monsterinfo.idle_time)
		{
			self->monsterinfo.idle (self);
			self->monsterinfo.idle_time = level.time + 15 + random() * 15;
		}
		else
		{
			self->monsterinfo.idle_time = level.time + random() * 15;
		}
	}
}


/*
=============
ai_walk

The monster is walking it's beat
=============
*/
void ai_walk (edict_t *self, float dist)
{
	M_MoveToGoal (self, dist);

	// check for noticing a player
	if (FindTarget (self))
		return;

	if ((self->monsterinfo.search) && (level.time > self->monsterinfo.idle_time))
	{
		if (self->monsterinfo.idle_time)
		{
			self->monsterinfo.search (self);
			self->monsterinfo.idle_time = level.time + 15 + random() * 15;
		}
		else
		{
			self->monsterinfo.idle_time = level.time + random() * 15;
		}
	}
}


/*
=============
ai_charge

Turns towards target and advances
Use this call with a distnace of 0 to replace ai_face
==============
*/
void ai_charge (edict_t *self, float dist)
{
	vec3_t	v;

	VectorSubtract (self->enemy->s.origin, self->s.origin, v);
	self->ideal_yaw = vectoyaw(v);
	M_ChangeYaw (self);

	if (dist)
		M_walkmove (self, self->s.angles[YAW], dist);
}


/*
=============
ai_turn

don't move, but turn towards ideal_yaw
Distance is for slight position adjustments needed by the animations
=============
*/
void ai_turn (edict_t *self, float dist)
{
	if (dist)
		M_walkmove (self, self->s.angles[YAW], dist);

	if (FindTarget (self))
		return;
	
	M_ChangeYaw (self);
}


/*

.enemy
Will be world if not currently angry at anyone.

.movetarget
The next path spot to walk toward.  If .enemy, ignore .movetarget.
When an enemy is killed, the monster will try to return to it's path.

.hunt_time
Set to time + something when the player is in sight, but movement straight for
him is blocked.  This causes the monster to use wall following code for
movement direction instead of sighting on the player.

.ideal_yaw
A yaw angle of the intended direction, which will be turned towards at up
to 45 deg / state.  If the enemy is in view and hunt_time is not active,
this will be the exact line towards the enemy.

.pausetime
A monster will leave it's stand state and head towards it's .movetarget when
time > .pausetime.

walkmove(angle, speed) primitive is all or nothing
*/

/*
=============
range

returns the range catagorization of an entity reletive to self
0	melee range, will become hostile even if back is turned
1	visibility and infront, or visibility and show hostile
2	infront and show hostile
3	only triggered by damage
=============
*/
int range (edict_t *self, edict_t *other)
{
	vec3_t	v;
	float	len;

	VectorSubtract (self->s.origin, other->s.origin, v);
	len = VectorLength (v);
	if (len < MELEE_DISTANCE)
		return RANGE_MELEE;
	if (len < 500)
		return RANGE_NEAR;
	if (len < 1000)
		return RANGE_MID;
	return RANGE_FAR;
}

/*
=============
visible

returns 1 if the entity is visible to self, even if not infront ()
=============
*/
qboolean visible (edict_t *self, edict_t *other)
{
	vec3_t	spot1;
	vec3_t	spot2;
	trace_t	trace;

	VectorCopy (self->s.origin, spot1);
	spot1[2] += self->viewheight;
	VectorCopy (other->s.origin, spot2);
	spot2[2] += other->viewheight;
	trace = gi.trace (spot1, vec3_origin, vec3_origin, spot2, self, MASK_OPAQUE);
	
	if (trace.fraction == 1.0)
		return true;
	return false;
}


/*
=============
infront

returns 1 if the entity is in front (in sight) of self
=============
*/
qboolean infront (edict_t *self, edict_t *other)
{
	vec3_t	vec;
	float	dot;
	vec3_t	forward;
	
	AngleVectors (self->s.angles, forward, NULL, NULL);
	VectorSubtract (other->s.origin, self->s.origin, vec);
	VectorNormalize (vec);
	dot = DotProduct (vec, forward);
	
	if (dot > 0.3)
		return true;
	return false;
}


//============================================================================

void HuntTarget (edict_t *self)
{
	vec3_t	vec;

	self->goalentity = self->enemy;
	if (self->monsterinfo.aiflags & AI_STAND_GROUND)
		self->monsterinfo.stand (self);
	else
		self->monsterinfo.run (self);
	VectorSubtract (self->enemy->s.origin, self->s.origin, vec);
	self->ideal_yaw = vectoyaw(vec);
	// wait a while before first attack
	if (!(self->monsterinfo.aiflags & AI_STAND_GROUND))
		AttackFinished (self, 1);
}

void FoundTarget (edict_t *self)
{
	// let other monsters see this monster for a while
	if (self->enemy->client)
	{
		level.sight_entity = self;
		level.sight_entity_framenum = level.framenum;
		level.sight_entity->light_level = 128;
	}

	self->show_hostile = level.time + 1;		// wake up other monsters

	VectorCopy(self->enemy->s.origin, self->monsterinfo.last_sighting);
	self->monsterinfo.trail_time = level.time;

	if (!self->combattarget)
	{
		HuntTarget (self);
		return;
	}

	self->goalentity = self->movetarget = G_PickTarget(self->combattarget);
	if (!self->movetarget)
	{
		self->goalentity = self->movetarget = self->enemy;
		HuntTarget (self);
		gi.dprintf("%s at %s, combattarget %s not found\n", self->classname, vtos(self->s.origin), self->combattarget);
		return;
	}

	// clear out our combattarget, these are a one shot deal
	self->combattarget = NULL;
	self->monsterinfo.aiflags |= AI_COMBAT_POINT;

	// clear the targetname, that point is ours!
	self->movetarget->targetname = NULL;
	self->monsterinfo.pausetime = 0;

	// run for it
	self->monsterinfo.run (self);
}


/*
===========
FindTarget

Self is currently not attacking anything, so try to find a target

Returns TRUE if an enemy was sighted

When a player fires a missile, the point of impact becomes a fakeplayer so
that monsters that see the impact will respond as if they had seen the
player.

To avoid spending too much time, only a single client (or fakeclient) is
checked each frame.  This means multi player games will have slightly
slower noticing monsters.
============
*/
qboolean FindTarget (edict_t *self)
{
	edict_t		*client;
	qboolean	heardit;
	int			r;

	if (self->monsterinfo.aiflags & AI_GOOD_GUY)
	{
		if (self->goalentity && self->goalentity->inuse && self->goalentity->classname)
		{
			if (strcmp(self->goalentity->classname, "target_actor") == 0)
				return false;
		}

		//FIXME look for monsters?
		return false;
	}

	// if we're going to a combat point, just proceed
	if (self->monsterinfo.aiflags & AI_COMBAT_POINT)
		return false;

// if the first spawnflag bit is set, the monster will only wake up on
// really seeing the player, not another monster getting angry or hearing
// something

// revised behavior so they will wake up if they "see" a player make a noise
// but not weapon impact/explosion noises

	heardit = false;
	if ((level.sight_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & 1) )
	{
		client = level.sight_entity;
		if (client->enemy == self->enemy)
		{
			return false;
		}
	}
	else if (level.sound_entity_framenum >= (level.framenum - 1))
	{
		client = level.sound_entity;
		heardit = true;
	}
	else if (!(self->enemy) && (level.sound2_entity_framenum >= (level.framenum - 1)) && !(self->spawnflags & 1) )
	{
		client = level.sound2_entity;
		heardit = true;
	}
	else
	{
		client = level.sight_client;
		if (!client)
			return false;	// no clients to get mad at
	}

	// if the entity went away, forget it
	if (!client->inuse)
		return false;

	if (client == self->enemy)
		return true;	// JDC false;

	if (client->client)
	{
		if (client->flags & FL_NOTARGET)
			return false;
	}
	else if (client->svflags & SVF_MONSTER)
	{
		if (!client->enemy)
			return false;
		if (client->enemy->flags & FL_NOTARGET)
			return false;
	}
	else if (heardit)
	{
		if (client->owner->flags & FL_NOTARGET)
			return false;
	}
	else
		return false;

	if (!heardit)
	{
		r = range (self, client);

		if (r == RANGE_FAR)
			return false;

// this is where we would check invisibility

		// is client in an spot too dark to be seen?
		if (client->light_level <= 5)
			return false;

		if (!visible (self, client))
		{
			return false;
		}

		if (r == RANGE_NEAR)
		{
			if (client->show_hostile < level.time && !infront (self, client))
			{
				return false;
			}
		}
		else if (r == RANGE_MID)
		{
			if (!infront (self, client))
			{
				return false;
			}
		}

		self->enemy = client;

		if (strcmp(self->enemy->classname, "player_noise") != 0)
		{
			self->monsterinfo.aiflags &= ~AI_SOUND_TARGET;

			if (!self->enemy->client)
			{
				self->enemy = self->enemy->enemy;
				if (!self->enemy->client)
				{
					self->enemy = NULL;
					return false;
				}
			}
		}
	}
	else	// heardit
	{
		vec3_t	temp;

		if (self->spawnflags & 1)
		{
			if (!visible (self, client))
				return false;
		}
		else
		{
			if (!gi.inPHS(self->s.origin, client->s.origin))
				return false;
		}

		VectorSubtract (client->s.origin, self->s.origin, temp);

		if (VectorLength(temp) > 1000)	// too far to hear
		{
			return false;
		}

?? 快捷鍵說明

復(fù)制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號(hào) Ctrl + =
減小字號(hào) Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日韩免费观看2025年上映的电影 | 国产欧美一区二区精品性色超碰| 国产iv一区二区三区| 一卡二卡欧美日韩| 久久―日本道色综合久久| 色成人在线视频| 日韩一区二区在线免费观看| 男女性色大片免费观看一区二区| 精品国产伦理网| 91精品国产91久久久久久一区二区| 国产成人一级电影| 青青青伊人色综合久久| 国产精品福利一区二区| 精品久久久久久久久久久院品网| 99久久er热在这里只有精品15 | 成人黄色在线看| 久久99最新地址| 五月天激情小说综合| 国产精品久久久久久久裸模| 精品少妇一区二区三区在线视频| 91.麻豆视频| 欧美视频中文字幕| 欧美色区777第一页| 欧美日韩一卡二卡| 日本电影亚洲天堂一区| 91美女精品福利| 91国偷自产一区二区开放时间 | 欧美日韩免费一区二区三区视频| 99久免费精品视频在线观看 | 不卡的av电影| 成人性视频免费网站| 成人av免费在线观看| 91麻豆国产福利在线观看| 欧美日韩精品系列| 宅男噜噜噜66一区二区66| 日韩精品最新网址| 久久欧美中文字幕| 亚洲欧美在线另类| 亚洲午夜电影在线| 日韩激情视频在线观看| 国产成人午夜视频| 国产精品18久久久久久久久| 成人免费视频一区| 欧美三级中文字幕| 精品福利视频一区二区三区| 欧美国产1区2区| 日韩精品乱码免费| 成人少妇影院yyyy| 欧美日韩国产美| 国产亚洲精品资源在线26u| 亚洲精品中文在线| 国产一区二区女| 欧美日韩高清一区二区| 中文字幕精品三区| 视频一区在线播放| 色综合久久天天| 国产三级精品三级| 欧美aaa在线| 国产高清视频一区| 欧美日韩免费在线视频| 国产精品久久久久久久久图文区 | 日韩不卡一区二区| 成人高清免费在线播放| 91精品在线麻豆| 一区二区三区国产| av成人老司机| 国产精品日日摸夜夜摸av| 美女任你摸久久| 91精品中文字幕一区二区三区| 亚洲视频网在线直播| 国产成人综合亚洲91猫咪| 2欧美一区二区三区在线观看视频 337p粉嫩大胆噜噜噜噜噜91av | 久久国产精品99久久人人澡| 欧美性受极品xxxx喷水| 综合在线观看色| 91免费视频网| 亚洲午夜久久久久久久久电影网 | 欧美亚洲动漫另类| 亚洲一区二区三区四区在线观看| 色婷婷av一区二区三区gif| 成人欧美一区二区三区小说 | 国产精品欧美久久久久一区二区 | 8v天堂国产在线一区二区| 免费久久99精品国产| 精品入口麻豆88视频| 国产精品99久久久久久久vr | 久久精品一区八戒影视| 成人黄色大片在线观看| 一区二区三区中文字幕电影 | 在线一区二区观看| 日日摸夜夜添夜夜添精品视频| 欧美va亚洲va香蕉在线| 国产精品一二三四区| 亚洲日本成人在线观看| 欧美日韩国产综合一区二区| 黄色日韩网站视频| 亚洲女同ⅹxx女同tv| 欧美一区二区三区在线| 国产精品亚洲视频| 一区二区三区精品久久久| 91精品国产入口| 成人黄页在线观看| 青青草91视频| 亚洲美女区一区| 中文字幕精品三区| 色8久久精品久久久久久蜜 | 日韩二区在线观看| 日本一区二区三区在线观看| 欧洲av一区二区嗯嗯嗯啊| 久久国内精品视频| 午夜视频一区在线观看| 亚洲色图一区二区三区| 26uuu国产电影一区二区| 欧美日韩美少妇| 99riav一区二区三区| 国产一区二区影院| 美国三级日本三级久久99| 一区二区三区四区不卡在线| 中文字幕一区二区三区在线不卡| www.欧美.com| 日韩精品国产精品| 亚洲国产精品麻豆| 一区二区三区在线观看视频| 国产精品污污网站在线观看| 精品久久久久一区| 精品精品欲导航| 精品国产髙清在线看国产毛片| 欧美久久久久免费| 欧美一区二区三级| 欧美日本在线播放| 88在线观看91蜜桃国自产| 制服视频三区第一页精品| 9191精品国产综合久久久久久| 欧美性大战xxxxx久久久| 欧美日韩专区在线| 在线不卡一区二区| 精品久久久久久久一区二区蜜臀| 日韩欧美一级二级三级| 精品1区2区在线观看| 国产欧美日韩另类视频免费观看| 国产农村妇女毛片精品久久麻豆| 国产人成一区二区三区影院| 久久久不卡影院| 亚洲欧洲精品一区二区三区| 一区二区三区成人在线视频| 免费在线观看一区二区三区| 丰满亚洲少妇av| 欧美色综合久久| 国产日韩精品一区二区三区| 亚洲精品中文字幕在线观看| 男人操女人的视频在线观看欧美| 国产伦精品一区二区三区视频青涩 | 国产一区二区0| 91黄色在线观看| 久久久亚洲精品一区二区三区| 亚洲人成精品久久久久| 黑人巨大精品欧美黑白配亚洲| 成人少妇影院yyyy| 欧美哺乳videos| 一区二区三区精品视频| 国产成人亚洲综合a∨猫咪| 欧美久久久久中文字幕| 一区二区在线免费观看| 国产乱色国产精品免费视频| 欧美色视频在线| 亚洲美女视频在线观看| 国产不卡一区视频| 日韩一级完整毛片| 亚洲综合一区二区| 91丨九色丨黑人外教| 久久久亚洲精品石原莉奈 | 91视频一区二区| 国产精品福利一区二区三区| 国产原创一区二区| 欧美sm美女调教| 国产精品亚洲一区二区三区在线| 欧美一三区三区四区免费在线看 | 国产成人亚洲综合a∨婷婷图片| 日韩亚洲欧美成人一区| 日本不卡高清视频| 欧美一级在线视频| 国产在线精品一区二区三区不卡| 欧美顶级少妇做爰| 日韩av网站在线观看| 91精品国产综合久久福利软件 | 制服.丝袜.亚洲.另类.中文| 日韩国产欧美在线播放| 精品日本一线二线三线不卡| 极品瑜伽女神91| 综合激情成人伊人| 国产精品夜夜嗨| 在线播放欧美女士性生活| 亚洲女同ⅹxx女同tv| 欧美色视频一区| 精品在线一区二区三区| 久久久亚洲精华液精华液精华液| 国产精品一二三四区| 亚洲在线视频网站| 欧美一区2区视频在线观看| 国产盗摄女厕一区二区三区|