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

📄 p_map.c

📁 使用Doom引擎开发的著名游戏《毁灭巫师》的源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
				}			}		}		else if(tmthing->type == MT_MSTAFF_FX2 && thing != tmthing->target)		{			if(!thing->player && !(thing->flags2&MF2_BOSS))			{				switch(thing->type)				{					case MT_FIGHTER_BOSS:	// these not flagged boss					case MT_CLERIC_BOSS:	// so they can be blasted					case MT_MAGE_BOSS:						break;					default:						P_DamageMobj(thing, tmthing, tmthing->target, 10);						return true;						break;				}			}		}		if(tmthing->target && tmthing->target->type == thing->type)		{ // Don't hit same species as originator			if(thing == tmthing->target)			{ // Don't missile self				return(true);			}			if(!thing->player)			{ // Hit same species as originator, explode, no damage				return(false);			}		}		if(!(thing->flags&MF_SHOOTABLE))		{ // Didn't do any damage			return!(thing->flags&MF_SOLID);		}		if(tmthing->flags2&MF2_RIP)		{			if (!(thing->flags&MF_NOBLOOD) &&				!(thing->flags2&MF2_REFLECTIVE) &&				!(thing->flags2&MF2_INVULNERABLE))			{ // Ok to spawn some blood				P_RipperBlood(tmthing);			}			//S_StartSound(tmthing, sfx_ripslop);			damage = ((P_Random()&3)+2)*tmthing->damage;			P_DamageMobj(thing, tmthing, tmthing->target, damage);			if(thing->flags2&MF2_PUSHABLE				&& !(tmthing->flags2&MF2_CANNOTPUSH))			{ // Push thing				thing->momx += tmthing->momx>>2;				thing->momy += tmthing->momy>>2;			}			numspechit = 0;			return(true);		}		// Do damage		damage = ((P_Random()%8)+1)*tmthing->damage;		if(damage)		{			if (!(thing->flags&MF_NOBLOOD) && 				!(thing->flags2&MF2_REFLECTIVE) &&				!(thing->flags2&MF2_INVULNERABLE) &&				!(tmthing->type == MT_TELOTHER_FX1) &&				!(tmthing->type == MT_TELOTHER_FX2) &&				!(tmthing->type == MT_TELOTHER_FX3) &&				!(tmthing->type == MT_TELOTHER_FX4) &&				!(tmthing->type == MT_TELOTHER_FX5) &&				(P_Random() < 192))			{				P_BloodSplatter(tmthing->x, tmthing->y, tmthing->z, thing);			}			P_DamageMobj(thing, tmthing, tmthing->target, damage);		}		return(false);	}	if(thing->flags2&MF2_PUSHABLE && !(tmthing->flags2&MF2_CANNOTPUSH))	{ // Push thing		thing->momx += tmthing->momx>>2;		thing->momy += tmthing->momy>>2;	}	// Check for special thing	if(thing->flags&MF_SPECIAL)	{		solid = thing->flags&MF_SOLID;		if(tmflags&MF_PICKUP)		{ // Can be picked up by tmthing			P_TouchSpecialThing(thing, tmthing); // Can remove thing		}		return(!solid);	}	return(!(thing->flags&MF_SOLID));}//---------------------------------------------------------------------------//// PIT_CheckOnmobjZ////---------------------------------------------------------------------------boolean PIT_CheckOnmobjZ(mobj_t *thing){	fixed_t blockdist;	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);	}	if(tmthing->z > thing->z+thing->height)	{		return(true);	}	else if(tmthing->z+tmthing->height < thing->z)	{ // under thing		return(true);	}	if(thing->flags&MF_SOLID)	{		onmobj = thing;	}	return(!(thing->flags&MF_SOLID));}/*===============================================================================						MOVEMENT CLIPPING===============================================================================*///----------------------------------------------------------------------------//// FUNC P_TestMobjLocation//// Returns true if the mobj is not blocked by anything at its current// location, otherwise returns false.////----------------------------------------------------------------------------boolean P_TestMobjLocation(mobj_t *mobj){	int flags;	flags = mobj->flags;	mobj->flags &= ~MF_PICKUP;	if(P_CheckPosition(mobj, mobj->x, mobj->y))	{ // XY is ok, now check Z		mobj->flags = flags;		if((mobj->z < mobj->floorz)			|| (mobj->z+mobj->height > mobj->ceilingz))		{ // Bad Z			return(false);		}		return(true);	}	mobj->flags = flags;	return(false);}/*==================== P_CheckPosition== This is purely informative, nothing is modified (except things picked up)in:a mobj_t (can be valid or invalid)a position to be checked (doesn't need to be related to the mobj_t->x,y)during:special things are touched if MF_PICKUPearly out on solid lines?out:newsubsecfloorzceilingztmdropoffz = the lowest point contacted (monsters won't move to a dropoff)speciallines[]numspeciallinesmobj_t *BlockingMobj = pointer to thing that blocked position (NULL if notblocked, or blocked by a line).==================*/boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y){	int                     xl,xh,yl,yh,bx,by;	subsector_t             *newsubsec;	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;	if(tmflags&MF_NOCLIP && !(tmflags&MF_SKULLFLY))	{		return true;	}//// check things first, possibly picking things up// the bounding box is extended by MAXRADIUS because mobj_ts are grouped// into mapblocks based on their origin point, and can overlap into adjacent// blocks by up to MAXRADIUS units//	xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;	xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;	yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;	yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;	BlockingMobj = NULL;	for (bx=xl ; bx<=xh ; bx++)		for (by=yl ; by<=yh ; by++)			if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))				return false;//// check lines//	if(tmflags&MF_NOCLIP)	{		return true;	}	BlockingMobj = NULL;	xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;	xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;	yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;	yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;	for (bx=xl ; bx<=xh ; bx++)		for (by=yl ; by<=yh ; by++)			if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))				return false;	return true;}//=============================================================================//// P_CheckOnmobj(mobj_t *thing)////              Checks if the new Z position is legal//=============================================================================mobj_t *P_CheckOnmobj(mobj_t *thing){	int                     xl,xh,yl,yh,bx,by;	subsector_t             *newsubsec;	fixed_t x;	fixed_t y;	mobj_t oldmo;	x = thing->x;	y = thing->y;	tmthing = thing;	tmflags = thing->flags;	oldmo = *thing; // save the old mobj before the fake zmovement	P_FakeZMovement(tmthing);	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;	if ( tmflags & MF_NOCLIP )		return NULL;//// check things first, possibly picking things up// the bounding box is extended by MAXRADIUS because mobj_ts are grouped// into mapblocks based on their origin point, and can overlap into adjacent// blocks by up to MAXRADIUS units//	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_CheckOnmobjZ))			{				*tmthing = oldmo;				return onmobj;			}	*tmthing = oldmo;	return NULL;}//=============================================================================//// P_FakeZMovement////              Fake the zmovement so that we can check if a move is legal//=============================================================================void P_FakeZMovement(mobj_t *mo){	int dist;	int delta;//// adjust height//	mo->z += mo->momz;	if(mo->flags&MF_FLOAT && mo->target)	{       // float down towards target if too close		if(!(mo->flags&MF_SKULLFLY) && !(mo->flags&MF_INFLOAT))		{			dist = P_AproxDistance(mo->x-mo->target->x, mo->y-mo->target->y);			delta =( mo->target->z+(mo->height>>1))-mo->z;			if (delta < 0 && dist < -(delta*3))				mo->z -= FLOATSPEED;			else if (delta > 0 && dist < (delta*3))				mo->z += FLOATSPEED;		}	}	if(mo->player && mo->flags2&MF2_FLY && !(mo->z <= mo->floorz)		&& leveltime&2)	{		mo->z += finesine[(FINEANGLES/20*leveltime>>2)&FINEMASK];	}//// clip movement//	if(mo->z <= mo->floorz)	{ // Hit the floor		mo->z = mo->floorz;		if(mo->momz < 0)		{			mo->momz = 0;		}		if(mo->flags&MF_SKULLFLY)		{ // The skull slammed into something			mo->momz = -mo->momz;		}		if(mo->info->crashstate && (mo->flags&MF_CORPSE))		{			return;		}	}	else if(mo->flags2&MF2_LOGRAV)	{		if(mo->momz == 0)			mo->momz = -(GRAVITY>>3)*2;		else			mo->momz -= GRAVITY>>3;	}	else if (! (mo->flags & MF_NOGRAVITY) )	{		if (mo->momz == 0)			mo->momz = -GRAVITY*2;		else			mo->momz -= GRAVITY;	}	if (mo->z + mo->height > mo->ceilingz)	{       // hit the ceiling		if (mo->momz > 0)			mo->momz = 0;		mo->z = mo->ceilingz - mo->height;		if (mo->flags & MF_SKULLFLY)		{       // the skull slammed into something			mo->momz = -mo->momz;		}	}}//===========================================================================//// CheckForPushSpecial////===========================================================================static void CheckForPushSpecial(line_t *line, int side, mobj_t *mobj){	if (line->special)	{		if(mobj->flags2&MF2_PUSHWALL)		{			P_ActivateLine(line, mobj, side, SPAC_PUSH);		}		else if(mobj->flags2&MF2_IMPACT)		{			P_ActivateLine(line, mobj, side, SPAC_IMPACT);		}		}}/*===================== P_TryMove== Attempt to move to a new position, crossing special lines unless MF_TELEPORT= is set====================*/boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y){	fixed_t         oldx, oldy;	int                     side, oldside;	line_t          *ld;	floatok = false;	if(!P_CheckPosition(thing, x, y))	{ // Solid wall or thing		if(!BlockingMobj || BlockingMobj->player 			|| !thing->player)		{ 			goto pushline;		}		else if (BlockingMobj->z+BlockingMobj->height-thing->z 			> 24*FRACUNIT 			|| (BlockingMobj->subsector->sector->ceilingheight			-(BlockingMobj->z+BlockingMobj->height) < thing->height)			|| (tmceilingz-(BlockingMobj->z+BlockingMobj->height) 			< thing->height))		{			goto pushline;		}	}	if(!(thing->flags&MF_NOCLIP))	{		if(tmceilingz-tmfloorz < thing->height)		{ // Doesn't fit			goto pushline;		}		floatok = true;		if(!(thing->flags&MF_TELEPORT)			&& tmceilingz-thing->z < thing->height			&& thing->type != MT_LIGHTNING_CEILING			&& !(thing->flags2&MF2_FLY))		{ // mobj must lower itself to fit			goto pushline;		}		if(thing->flags2&MF2_FLY)		{			if(thing->z+thing->height > tmceilingz)			{				thing->momz = -8*FRACUNIT;				goto pushline;			}			else if(thing->z < tmfloorz && tmfloorz-tmdropoffz > 24*FRACUNIT)			{				thing->momz = 8*FRACUNIT;				goto pushline;			}		}		if(!(thing->flags&MF_TELEPORT)			// The Minotaur floor fire (MT_MNTRFX2) can step up any amount			&& thing->type != MT_MNTRFX2 && thing->type != MT_LIGHTNING_FLOOR			&& tmfloorz-thing->z > 24*FRACUNIT)		{			goto pushline;		}		if (!(thing->flags&(MF_DROPOFF|MF_FLOAT)) && 			(tmfloorz-tmdropoffz > 24*FRACUNIT) &&			!(thing->flags2&MF2_BLASTED))		{ // Can't move over a dropoff unless it's been blasted				return(false);		}		if(thing->flags2&MF2_CANTLEAVEFLOORPIC 			&& (tmfloorpic != thing->subsector->sector->floorpic				|| tmfloorz-thing->z != 0))		{ // must stay within a sector of a certain floor type			return false;		}	}//// the move is ok, so link the thing into its new position//	P_UnsetThingPosition (thing);	oldx = thing->x;	oldy = thing->y;	thing->floorz = tmfloorz;	thing->ceilingz = tmceilingz;	thing->floorpic = tmfloorpic;	thing->x = x;	thing->y = y;	P_SetThingPosition (thing);	if(thing->flags2&MF2_FLOORCLIP)	{		if(thing->z == thing->subsector->sector->floorheight			&& P_GetThingFloorType(thing) >= FLOOR_LIQUID)		{			thing->floorclip = 10*FRACUNIT;		}		else 		{			thing->floorclip = 0;		}	}//// if any special lines were hit, do the effect//	if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )	{		while (numspechit > 0)		{			numspechit--;			// see if the line was crossed			ld = spechit[numspechit];			side = P_PointOnLineSide (thing->x, thing->y, ld);			oldside = P_PointOnLineSide (oldx, oldy, ld);			if (side != oldside)			{				if (ld->special)				{					if(thing->player)					{						P_ActivateLine(ld, thing, oldside, SPAC_CROSS);					}					else if(thing->flags2&MF2_MCROSS)					{						P_ActivateLine(ld, thing, oldside, SPAC_MCROSS);					}					else if(thing->flags2&MF2_PCROSS)					{						P_ActivateLine(ld, thing, oldside, SPAC_PCROSS);

⌨️ 快捷键说明

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