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

📄 p_map.c

📁 使用Doom引擎开发的著名游戏《毁灭巫师》的源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
//**************************************************************************//**//** p_map.c : Heretic 2 : Raven Software, Corp.//**//** $RCSfile: p_map.c,v $//** $Revision: 1.107 $//** $Date: 95/10/13 04:26:47 $//** $Author: paul $//**//**************************************************************************#include "h2def.h"#include "p_local.h"#include "soundst.h"static void CheckForPushSpecial(line_t *line, int side, mobj_t *mobj);/*===============================================================================NOTES:===============================================================================*//*===============================================================================mobj_t NOTESmobj_ts are used to tell the refresh where to draw an image, tell the world simulation when objects are contacted, and tell the sound driver how to position a sound.The refresh uses the next and prev links to follow lists of things in sectors as they are being drawn.  The sprite, frame, and angle elements determine which patch_t is used to draw the sprite if it is visible.  The sprite and frame values are allmost allways set from state_t structures.  The statescr.exe utility generates the states.h and states.c files that contain the sprite/frame numbers from the statescr.txt source file.  The xyz origin point represents a point at the bottom middle of the sprite (between the feet of a biped).  This is the default origin position for patch_ts grabbed with lumpy.exe.  A walking creature will have its z equal to the floor it is standing on.The sound code uses the x,y, and subsector fields to do stereo positioning of any sound effited by the mobj_t.The play simulation uses the blocklinks, x,y,z, radius, height to determine when mobj_ts are touching each other, touching lines in the map, or hit by trace lines (gunshots, lines of sight, etc). The mobj_t->flags element has various bit flags used by the simulation.Every mobj_t is linked into a single sector based on it's origin coordinates.The subsector_t is found with R_PointInSubsector(x,y), and the sector_t can be found with subsector->sector.  The sector links are only used by the rendering code,  the play simulation does not care about them at all.Any mobj_t that needs to be acted upon be something else in the play world (block movement, be shot, etc) will also need to be linked into the blockmap.  If the thing has the MF_NOBLOCK flag set, it will not use the block links. It can still interact with other things, but only as the instigator (missiles will run into other things, but nothing can run into a missile).   Each block in the grid is 128*128 units, and knows about every line_t that it contains a piece of, and every interactable mobj_t that has it's origin contained.A valid mobj_t is a mobj_t that has the proper subsector_t filled in for it's xy coordinates and is linked into the subsector's sector or has the MF_NOSECTOR flag set (the subsector_t needs to be valid even if MF_NOSECTOR is set), and is linked into a blockmap block or has the MF_NOBLOCKMAP flag set.  Links should only be modified by the P_[Un]SetThingPosition () functions.  Do not change the MF_NO? flags while a thing is valid.===============================================================================*/fixed_t         tmbbox[4];mobj_t          *tmthing;mobj_t			 *tsthing;int                     tmflags;fixed_t         tmx, tmy;boolean         floatok;	// if true, move would be ok if							// within tmfloorz - tmceilingzfixed_t tmfloorz, tmceilingz, tmdropoffz;int tmfloorpic;// keep track of the line that lowers the ceiling, so missiles don't explode// against sky hack wallsline_t *ceilingline;// keep track of special lines as they are hit, but don't process them// until the move is proven valid#define MAXSPECIALCROSS 8line_t *spechit[MAXSPECIALCROSS];int numspechit;mobj_t *onmobj; // generic global onmobj...used for landing on pods/playersmobj_t *BlockingMobj;/*===============================================================================					TELEPORT MOVE===============================================================================*//*==================== PIT_StompThing===================*/boolean PIT_StompThing (mobj_t *thing){	fixed_t         blockdist;	if (!(thing->flags & MF_SHOOTABLE) )		return true;	blockdist = thing->radius + tmthing->radius;	if ( abs(thing->x - tmx) >= blockdist || abs(thing->y - tmy) >= blockdist )		return true;            // didn't hit it	if (thing == tmthing)		return true;            // don't clip against self	if(!(tmthing->flags2&MF2_TELESTOMP))	{ // Not allowed to stomp things		return(false);	}	P_DamageMobj (thing, tmthing, tmthing, 10000);	return true;}/*===================== P_TeleportMove====================*/boolean P_TeleportMove (mobj_t *thing, fixed_t x, fixed_t y){	int                     xl,xh,yl,yh,bx,by;	subsector_t             *newsubsec;//// kill anything occupying the position//	tmthing = thing;	tmflags = thing->flags;	tmx = x;	tmy = y;	tmbbox[BOXTOP] = y + tmthing->radius;	tmbbox[BOXBOTTOM] = y - tmthing->radius;	tmbbox[BOXRIGHT] = x + tmthing->radius;	tmbbox[BOXLEFT] = x - tmthing->radius;	newsubsec = R_PointInSubsector (x,y);	ceilingline = NULL;//// the base floor / ceiling is from the subsector that contains the// point.  Any contacted lines the step closer together will adjust them//	tmfloorz = tmdropoffz = newsubsec->sector->floorheight;	tmceilingz = newsubsec->sector->ceilingheight;	tmfloorpic = newsubsec->sector->floorpic;	validcount++;	numspechit = 0;//// stomp on any things contacted//	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;	for (bx=xl ; bx<=xh ; bx++)		for (by=yl ; by<=yh ; by++)			if (!P_BlockThingsIterator(bx,by,PIT_StompThing))				return false;//// the move is ok, so link the thing into its new position//	P_UnsetThingPosition (thing);	thing->floorz = tmfloorz;	thing->ceilingz = tmceilingz;	thing->x = x;	thing->y = y;	P_SetThingPosition (thing);	return true;}boolean PIT_ThrustStompThing (mobj_t *thing){	fixed_t         blockdist;	if (!(thing->flags & MF_SHOOTABLE) )		return true;	blockdist = thing->radius + tsthing->radius;	if ( abs(thing->x - tsthing->x) >= blockdist || 		  abs(thing->y - tsthing->y) >= blockdist ||			(thing->z > tsthing->z+tsthing->height) )		return true;            // didn't hit it	if (thing == tsthing)		return true;            // don't clip against self	P_DamageMobj (thing, tsthing, tsthing, 10001);	tsthing->args[1] = 1;	// Mark thrust thing as bloody	return true;}void PIT_ThrustSpike(mobj_t *actor){	int xl,xh,yl,yh,bx,by;	int x0,x2,y0,y2;	tsthing = actor;	x0 = actor->x - actor->info->radius;	x2 = actor->x + actor->info->radius;	y0 = actor->y - actor->info->radius;	y2 = actor->y + actor->info->radius;	xl = (x0 - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;	xh = (x2 - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;	yl = (y0 - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;	yh = (y2 - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;	// stomp on any things contacted	for (bx=xl ; bx<=xh ; bx++)		for (by=yl ; by<=yh ; by++)			P_BlockThingsIterator(bx,by,PIT_ThrustStompThing);}/*===============================================================================					MOVEMENT ITERATOR FUNCTIONS===============================================================================*//*==================== PIT_CheckLine== Adjusts tmfloorz and tmceilingz as lines are contacted==================*/boolean PIT_CheckLine(line_t *ld){	if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]		||      tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]		||      tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]		||      tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])	{		return(true);	}	if(P_BoxOnLineSide(tmbbox, ld) != -1)	{		return(true);	}// a line has been hit/*== The moving thing's destination position will cross the given line.= If this should not be allowed, return false.= If the line is special, keep track of it to process later if the move=       is proven ok.  NOTE: specials are NOT sorted by order, so two special lines=       that are only 8 pixels apart could be crossed in either order.*/	if(!ld->backsector)	{ // One sided line		if (tmthing->flags2&MF2_BLASTED)		{			P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass>>5);		}		CheckForPushSpecial(ld, 0, tmthing);		return(false);	}	if(!(tmthing->flags&MF_MISSILE))	{		if(ld->flags&ML_BLOCKING)		{ // Explicitly blocking everything			if (tmthing->flags2&MF2_BLASTED)			{				P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass>>5);			}			CheckForPushSpecial(ld, 0, tmthing);			return(false);		}		if(!tmthing->player && ld->flags&ML_BLOCKMONSTERS)		{ // Block monsters only			if (tmthing->flags2&MF2_BLASTED)			{				P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass>>5);			}			return(false);		}	}	P_LineOpening(ld);              // set openrange, opentop, openbottom	// adjust floor / ceiling heights	if(opentop < tmceilingz)	{		tmceilingz = opentop;		ceilingline = ld;	}	if(openbottom > tmfloorz)	{		tmfloorz = openbottom;	}	if(lowfloor < tmdropoffz)	{		tmdropoffz = lowfloor;	}	if(ld->special)	{ // Contacted a special line, add it to the list		spechit[numspechit] = ld;		numspechit++;	}	return(true);}//---------------------------------------------------------------------------//// FUNC PIT_CheckThing////---------------------------------------------------------------------------boolean PIT_CheckThing(mobj_t *thing){	fixed_t blockdist;	boolean solid;	int damage;	if(!(thing->flags&(MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)))	{ // Can't hit thing		return(true);	}	blockdist = thing->radius+tmthing->radius;	if(abs(thing->x-tmx) >= blockdist || abs(thing->y-tmy) >= blockdist)	{ // Didn't hit thing		return(true);	}	if(thing == tmthing)	{ // Don't clip against self		return(true);	}	BlockingMobj = thing; 	if(tmthing->flags2&MF2_PASSMOBJ)	{ // check if a mobj passed over/under another object		if(tmthing->type == MT_BISHOP && thing->type == MT_BISHOP)		{ // don't let bishops fly over other bishops			return false;		}		if(tmthing->z >= thing->z+thing->height			&& !(thing->flags&MF_SPECIAL))		{			return(true);		}		else if(tmthing->z+tmthing->height < thing->z			&& !(thing->flags&MF_SPECIAL))		{ // under thing			return(true);		}	}	// Check for skulls slamming into things	if(tmthing->flags&MF_SKULLFLY)	{		if(tmthing->type == MT_MINOTAUR)		{			// Slamming minotaurs shouldn't move non-creatures			if (!(thing->flags&MF_COUNTKILL))			{				return(false);			}		}		else if(tmthing->type == MT_HOLY_FX)		{			if(thing->flags&MF_SHOOTABLE && thing != tmthing->target)			{				if(netgame && !deathmatch && thing->player)				{ // don't attack other co-op players					return true;				}				if(thing->flags2&MF2_REFLECTIVE					&& (thing->player || thing->flags2&MF2_BOSS))				{					tmthing->special1 = (int)tmthing->target;					tmthing->target = thing;					return true;				}				if(thing->flags&MF_COUNTKILL || thing->player)				{					tmthing->special1 = (int)thing;				}				if(P_Random() < 96)				{					damage = 12;					if(thing->player || thing->flags2&MF2_BOSS)					{						damage = 3;						// ghost burns out faster when attacking players/bosses						tmthing->health -= 6;					}					P_DamageMobj(thing, tmthing, tmthing->target, damage);					if(P_Random() < 128)					{						P_SpawnMobj(tmthing->x, tmthing->y, tmthing->z,							MT_HOLY_PUFF);						S_StartSound(tmthing, SFX_SPIRIT_ATTACK);						if(thing->flags&MF_COUNTKILL && P_Random() < 128						&& !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT))						{							if ((thing->type == MT_CENTAUR) ||								(thing->type == MT_CENTAURLEADER) ||								(thing->type == MT_ETTIN))							{								S_StartSound(thing, SFX_PUPPYBEAT);							}						}					}				}				if(thing->health <= 0)				{					tmthing->special1 = 0;				}			}			return true;		}		damage = ((P_Random()%8)+1)*tmthing->damage;		P_DamageMobj(thing, tmthing, tmthing, damage);		tmthing->flags &= ~MF_SKULLFLY;		tmthing->momx = tmthing->momy = tmthing->momz = 0;		P_SetMobjState(tmthing, tmthing->info->seestate);		return(false);	}	// Check for blasted thing running into another	if(tmthing->flags2&MF2_BLASTED && thing->flags&MF_SHOOTABLE)	{		if (!(thing->flags2&MF2_BOSS) &&			(thing->flags&MF_COUNTKILL))		{			thing->momx += tmthing->momx;			thing->momy += tmthing->momy;			if ((thing->momx + thing->momy) > 3*FRACUNIT)			{				damage = (tmthing->info->mass/100)+1;				P_DamageMobj(thing, tmthing, tmthing, damage);				damage = (thing->info->mass/100)+1;				P_DamageMobj(tmthing, thing, thing, damage>>2);			}			return(false);		}	}	// Check for missile	if(tmthing->flags&MF_MISSILE)	{		// Check for a non-shootable mobj		if(thing->flags2&MF2_NONSHOOTABLE)		{			return true;		}		// Check if it went over / under		if(tmthing->z > thing->z+thing->height)		{ // Over thing			return(true);		}		if(tmthing->z+tmthing->height < thing->z)		{ // Under thing			return(true);		}		if(tmthing->flags2&MF2_FLOORBOUNCE)		{			if(tmthing->target == thing || !(thing->flags&MF_SOLID))			{				return true;			}			else			{				return false;			}		}		if(tmthing->type == MT_LIGHTNING_FLOOR			|| tmthing->type == MT_LIGHTNING_CEILING)		{			if(thing->flags&MF_SHOOTABLE && thing != tmthing->target)			{				if(thing->info->mass != MAXINT)				{					thing->momx += tmthing->momx>>4;					thing->momy += tmthing->momy>>4;				}				if((!thing->player && !(thing->flags2&MF2_BOSS))					|| !(leveltime&1))				{					if(thing->type == MT_CENTAUR 					|| thing->type == MT_CENTAURLEADER)					{ // Lightning does more damage to centaurs						P_DamageMobj(thing, tmthing, tmthing->target, 9);					}					else					{						P_DamageMobj(thing, tmthing, tmthing->target, 3);					}					if(!(S_GetSoundPlayingInfo(tmthing, 						SFX_MAGE_LIGHTNING_ZAP)))					{						S_StartSound(tmthing, SFX_MAGE_LIGHTNING_ZAP);					}					if(thing->flags&MF_COUNTKILL && P_Random() < 64 					&& !S_GetSoundPlayingInfo(thing, SFX_PUPPYBEAT))					{						if ((thing->type == MT_CENTAUR) ||							(thing->type == MT_CENTAURLEADER) ||							(thing->type == MT_ETTIN))						{							S_StartSound(thing, SFX_PUPPYBEAT);						}					}				}				tmthing->health--;				if(tmthing->health <= 0 || thing->health <= 0)				{					return false;				}				if(tmthing->type == MT_LIGHTNING_FLOOR)				{					if(tmthing->special2 						&& !((mobj_t *)tmthing->special2)->special1)					{						((mobj_t *)tmthing->special2)->special1 = 							(int)thing;					}				}				else if(!tmthing->special1)				{					tmthing->special1 = (int)thing;				}			}			return true; // lightning zaps through all sprites		}		else if(tmthing->type == MT_LIGHTNING_ZAP)		{			mobj_t *lmo;			if(thing->flags&MF_SHOOTABLE && thing != tmthing->target)			{							lmo = (mobj_t *)tmthing->special2;				if(lmo)				{					if(lmo->type == MT_LIGHTNING_FLOOR)					{						if(lmo->special2 							&& !((mobj_t *)lmo->special2)->special1)						{							((mobj_t *)lmo->special2)->special1 = (int)thing;						}					}					else if(!lmo->special1)					{						lmo->special1 = (int)thing;					}					if(!(leveltime&3))					{						lmo->health--;					}

⌨️ 快捷键说明

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