⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 p_enemy.c

📁 制作游戏 魔法师传奇 源代码设计 MOFASHICHUANQI 经典老游戏
💻 C
📖 第 1 页 / 共 5 页
字号:
//**************************************************************************//**//** p_enemy.c : Heretic 2 : Raven Software, Corp.//**//** $RCSfile: p_enemy.c,v $//** $Revision: 1.170 $//** $Date: 96/01/06 03:23:28 $//** $Author: bgokey $//**//**************************************************************************#include "h2def.h"#include "p_local.h"#include "soundst.h"// Macros// Types// Private Data// External Dataextern fixed_t FloatBobOffsets[64];//----------------------------------------------------------------------------//// PROC P_RecursiveSound////----------------------------------------------------------------------------mobj_t *soundtarget;void P_RecursiveSound(sector_t *sec, int soundblocks){	int i;	line_t *check;	sector_t *other;	// Wake up all monsters in this sector	if(sec->validcount == validcount && sec->soundtraversed <= soundblocks+1)	{ // Already flooded		return;	}	sec->validcount = validcount;	sec->soundtraversed = soundblocks+1;	sec->soundtarget = soundtarget;	for(i = 0; i < sec->linecount; i++)	{		check = sec->lines[i];		if(!(check->flags&ML_TWOSIDED))		{			continue;		}		P_LineOpening(check);		if(openrange <= 0)		{ // Closed door			continue;		}		if(sides[check->sidenum[0]].sector == sec)		{			other = sides[check->sidenum[1]].sector;		}		else		{			other = sides[check->sidenum[0]].sector;		}		if(check->flags&ML_SOUNDBLOCK)		{			if(!soundblocks)			{				P_RecursiveSound(other, 1);			}		}		else		{			P_RecursiveSound(other, soundblocks);		}	}}//----------------------------------------------------------------------------//// PROC P_NoiseAlert//// If a monster yells at a player, it will alert other monsters to the// player.////----------------------------------------------------------------------------void P_NoiseAlert(mobj_t *target, mobj_t *emmiter){	soundtarget = target;	validcount++;	P_RecursiveSound(emmiter->subsector->sector, 0);}//----------------------------------------------------------------------------//// FUNC P_CheckMeleeRange////----------------------------------------------------------------------------boolean P_CheckMeleeRange(mobj_t *actor){	mobj_t *mo;	fixed_t dist;	if(!actor->target)	{		return(false);	}	mo = actor->target;	dist = P_AproxDistance(mo->x-actor->x, mo->y-actor->y);	if(dist >= MELEERANGE)	{		return(false);	}	if(!P_CheckSight(actor, mo))	{		return(false);	}	if(mo->z > actor->z+actor->height)	{ // Target is higher than the attacker		return(false);	}	else if(actor->z > mo->z+mo->height)	{ // Attacker is higher		return(false);	}	return(true);}//----------------------------------------------------------------------------//// FUNC P_CheckMeleeRange2////----------------------------------------------------------------------------boolean P_CheckMeleeRange2(mobj_t *actor){	mobj_t *mo;	fixed_t dist;	if(!actor->target)	{		return(false);	}	mo = actor->target;	dist = P_AproxDistance(mo->x-actor->x, mo->y-actor->y);	if(dist >= MELEERANGE*2 || dist < MELEERANGE)	{		return(false);	}	if(!P_CheckSight(actor, mo))	{		return(false);	}	if(mo->z > actor->z+actor->height)	{ // Target is higher than the attacker		return(false);	}	else if(actor->z > mo->z+mo->height)	{ // Attacker is higher		return(false);	}	return(true);}//----------------------------------------------------------------------------//// FUNC P_CheckMissileRange////----------------------------------------------------------------------------boolean P_CheckMissileRange(mobj_t *actor){	fixed_t dist;	if(!P_CheckSight(actor, actor->target))	{		return(false);	}	if(actor->flags&MF_JUSTHIT)	{ // The target just hit the enemy, so fight back!		actor->flags &= ~MF_JUSTHIT;		return(true);	}	if(actor->reactiontime)	{ // Don't attack yet		return(false);	}	dist = (P_AproxDistance(actor->x-actor->target->x,		actor->y-actor->target->y)>>FRACBITS)-64;	if(!actor->info->meleestate)	{ // No melee attack, so fire more frequently		dist -= 128;	}	if(dist > 200)	{		dist = 200;	}	if(P_Random() < dist)	{		return(false);	}	return(true);}/*================== P_Move== Move in the current direction= returns false if the move is blocked================*/fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};#define MAXSPECIALCROSS         8extern  line_t  *spechit[MAXSPECIALCROSS];extern  int                      numspechit;boolean P_Move(mobj_t *actor){	fixed_t tryx, tryy;	line_t *ld;	boolean good;	if(actor->flags2&MF2_BLASTED) return(true);	if(actor->movedir == DI_NODIR)	{		return(false);	}	tryx = actor->x+actor->info->speed*xspeed[actor->movedir];	tryy = actor->y+actor->info->speed*yspeed[actor->movedir];	if(!P_TryMove(actor, tryx, tryy))	{ // open any specials		if(actor->flags&MF_FLOAT && floatok)		{ // must adjust height			if(actor->z < tmfloorz)			{				actor->z += FLOATSPEED;			}			else			{				actor->z -= FLOATSPEED;			}			actor->flags |= MF_INFLOAT;			return(true);		}		if(!numspechit)		{			return false;		}		actor->movedir = DI_NODIR;		good = false;		while(numspechit--)		{			ld = spechit[numspechit];			// if the special isn't a door that can be opened, return false			if(P_ActivateLine(ld, actor, 0, SPAC_USE))			{				good = true;			}/* Old version before use/cross/impact specials were combined			if(P_UseSpecialLine(actor, ld))			{				good = true;			}*/		}		return(good);	}	else	{		actor->flags &= ~MF_INFLOAT;	}	if(!(actor->flags&MF_FLOAT))	{		if(actor->z > actor->floorz)		{			P_HitFloor(actor);		}		actor->z = actor->floorz;	}	return(true);}//----------------------------------------------------------------------------//// FUNC P_TryWalk//// Attempts to move actor in its current (ob->moveangle) direction.// If blocked by either a wall or an actor returns FALSE.// If move is either clear of block only by a door, returns TRUE and sets.// If a door is in the way, an OpenDoor call is made to start it opening.////----------------------------------------------------------------------------boolean P_TryWalk(mobj_t *actor){	if(!P_Move(actor))	{		return(false);	}	actor->movecount = P_Random()&15;	return(true);}/*================== P_NewChaseDir=================*/dirtype_t opposite[] ={DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST,DI_NORTH, DI_NORTHWEST, DI_NODIR};dirtype_t diags[] = {DI_NORTHWEST,DI_NORTHEAST,DI_SOUTHWEST,DI_SOUTHEAST};void P_NewChaseDir (mobj_t *actor){	fixed_t         deltax,deltay;	dirtype_t       d[3];	dirtype_t       tdir, olddir, turnaround;	if (!actor->target)		I_Error ("P_NewChaseDir: called with no target");	olddir = actor->movedir;	turnaround=opposite[olddir];	deltax = actor->target->x - actor->x;	deltay = actor->target->y - actor->y;	if (deltax>10*FRACUNIT)		d[1]= DI_EAST;	else if (deltax<-10*FRACUNIT)		d[1]= DI_WEST;	else		d[1]=DI_NODIR;	if (deltay<-10*FRACUNIT)		d[2]= DI_SOUTH;	else if (deltay>10*FRACUNIT)		d[2]= DI_NORTH;	else		d[2]=DI_NODIR;// try direct route	if (d[1] != DI_NODIR && d[2] != DI_NODIR)	{		actor->movedir = diags[((deltay<0)<<1)+(deltax>0)];		if (actor->movedir != turnaround && P_TryWalk(actor))			return;	}// try other directions	if (P_Random() > 200 ||  abs(deltay)>abs(deltax))	{		tdir=d[1];		d[1]=d[2];		d[2]=tdir;	}	if (d[1]==turnaround)		d[1]=DI_NODIR;	if (d[2]==turnaround)		d[2]=DI_NODIR;	if (d[1]!=DI_NODIR)	{		actor->movedir = d[1];		if (P_TryWalk(actor))			return;     /*either moved forward or attacked*/	}	if (d[2]!=DI_NODIR)	{		actor->movedir =d[2];		if (P_TryWalk(actor))			return;	}/* there is no direct path to the player, so pick another direction */	if (olddir!=DI_NODIR)	{		actor->movedir =olddir;		if (P_TryWalk(actor))			return;	}	if (P_Random()&1)       /*randomly determine direction of search*/	{		for (tdir=DI_EAST ; tdir<=DI_SOUTHEAST ; tdir++)		{			if (tdir!=turnaround)			{				actor->movedir =tdir;				if ( P_TryWalk(actor) )					return;			}		}	}	else	{		for (tdir=DI_SOUTHEAST ; tdir >= DI_EAST;tdir--)		{			if (tdir!=turnaround)			{				actor->movedir =tdir;				if ( P_TryWalk(actor) )				return;			}		}	}	if (turnaround !=  DI_NODIR)	{		actor->movedir =turnaround;		if ( P_TryWalk(actor) )			return;	}	actor->movedir = DI_NODIR;              // can't move}//---------------------------------------------------------------------------//// FUNC P_LookForMonsters////---------------------------------------------------------------------------#define MONS_LOOK_RANGE (16*64*FRACUNIT)#define MONS_LOOK_LIMIT 64boolean P_LookForMonsters(mobj_t *actor){	int count;	mobj_t *mo;	thinker_t *think;	if(!P_CheckSight(players[0].mo, actor))	{ // Player can't see monster		return(false);	}	count = 0;	for(think = thinkercap.next; think != &thinkercap; think = think->next)	{		if(think->function != P_MobjThinker)		{ // Not a mobj thinker			continue;		}		mo = (mobj_t *)think;		if(!(mo->flags&MF_COUNTKILL) || (mo == actor) || (mo->health <= 0))		{ // Not a valid monster			continue;		}		if(P_AproxDistance(actor->x-mo->x, actor->y-mo->y)			> MONS_LOOK_RANGE)		{ // Out of range			continue;		}		if(P_Random() < 16)		{ // Skip			continue;		}		if(count++ > MONS_LOOK_LIMIT)		{ // Stop searching			return(false);		}		if(!P_CheckSight(actor, mo))		{ // Out of sight			continue;		}		if (actor->type == MT_MINOTAUR)		{			if ((mo->type == MT_MINOTAUR) && 				 (mo->target != ((player_t *)actor->special1)->mo))			{				continue;			}		}		// Found a target monster		actor->target = mo;		return(true);	}	return(false);}/*================== P_LookForPlayers== If allaround is false, only look 180 degrees in front= returns true if a player is targeted================*/boolean P_LookForPlayers(mobj_t *actor, boolean allaround){	int c;	int stop;	player_t *player;	sector_t *sector;	angle_t an;	fixed_t dist;	if(!netgame && players[0].health <= 0)	{ // Single player game and player is dead, look for monsters		return(P_LookForMonsters(actor));	}	sector = actor->subsector->sector;	c = 0;	stop = (actor->lastlook-1)&3;	for( ; ; actor->lastlook = (actor->lastlook+1)&3 )	{		if (!playeringame[actor->lastlook])			continue;		if (c++ == 2 || actor->lastlook == stop)			return false;           // done looking		player = &players[actor->lastlook];		if (player->health <= 0)			continue;               // dead		if (!P_CheckSight (actor, player->mo))			continue;               // out of sight		if (!allaround)		{			an = R_PointToAngle2 (actor->x, actor->y,			player->mo->x, player->mo->y) - actor->angle;			if (an > ANG90 && an < ANG270)			{				dist = P_AproxDistance (player->mo->x - actor->x,					player->mo->y - actor->y);				// if real close, react anyway				if (dist > MELEERANGE)					continue;               // behind back			}		}		if(player->mo->flags&MF_SHADOW)		{ // Player is invisible			if((P_AproxDistance(player->mo->x-actor->x,				player->mo->y-actor->y) > 2*MELEERANGE)				&& P_AproxDistance(player->mo->momx, player->mo->momy)				< 5*FRACUNIT)			{ // Player is sneaking - can't detect				return(false);			}			if(P_Random() < 225)			{ // Player isn't sneaking, but still didn't detect				return(false);			}		}		if (actor->type == MT_MINOTAUR)		{			if(((player_t *)(actor->special1)) == player)			{				continue;			// Don't target master			}		}		actor->target = player->mo;		return(true);	}	return(false);}/*===============================================================================						ACTION ROUTINES===============================================================================*//*================ A_Look== Stay in state until a player is sighted===============*/void A_Look (mobj_t *actor){	mobj_t          *targ;	actor->threshold = 0;           // any shot will wake up	targ = actor->subsector->sector->soundtarget;	if (targ && (targ->flags & MF_SHOOTABLE) )	{		actor->target = targ;		if ( actor->flags & MF_AMBUSH )		{			if (P_CheckSight (actor, actor->target))				goto seeyou;		}		else			goto seeyou;	}	if (!P_LookForPlayers (actor, false) )		return;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -