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

📄 p_map.c

📁 使用Doom引擎开发的著名游戏《毁灭巫师》的源代码。
💻 C
📖 第 1 页 / 共 4 页
字号:
					}				}			}		}	}	return true;pushline:	if(!(thing->flags&(MF_TELEPORT|MF_NOCLIP)))	{		int numSpecHitTemp;		if (tmthing->flags2&MF2_BLASTED)		{			P_DamageMobj(tmthing, NULL, NULL, tmthing->info->mass>>5);		}		numSpecHitTemp = numspechit;		while (numSpecHitTemp > 0)		{			numSpecHitTemp--;			// see if the line was crossed			ld = spechit[numSpecHitTemp];			side = P_PointOnLineSide (thing->x, thing->y, ld);			CheckForPushSpecial(ld, side, thing);		}	}	return false;}/*==================== P_ThingHeightClip== Takes a valid thing and adjusts the thing->floorz, thing->ceilingz,= anf possibly thing->z== This is called for all nearby monsters whenever a sector changes height== If the thing doesn't fit, the z will be set to the lowest value and= false will be returned==================*/boolean P_ThingHeightClip (mobj_t *thing){	boolean         onfloor;	onfloor = (thing->z == thing->floorz);	P_CheckPosition (thing, thing->x, thing->y);	// what about stranding a monster partially off an edge?	thing->floorz = tmfloorz;	thing->ceilingz = tmceilingz;	thing->floorpic = tmfloorpic;	if (onfloor)	{ // walking monsters rise and fall with the floor		if((thing->z-thing->floorz < 9*FRACUNIT) 			|| (thing->flags&MF_NOGRAVITY))		{ 			thing->z = thing->floorz;		}	}	else	{       // don't adjust a floating monster unless forced to		if (thing->z+thing->height > thing->ceilingz)			thing->z = thing->ceilingz - thing->height;	}	if (thing->ceilingz - thing->floorz < thing->height)		return false;	return true;}/*==============================================================================							SLIDE MOVEAllows the player to slide along any angled walls==============================================================================*/fixed_t         bestslidefrac, secondslidefrac;line_t          *bestslideline, *secondslideline;mobj_t          *slidemo;fixed_t         tmxmove, tmymove;/*==================== P_HitSlideLine== Adjusts the xmove / ymove so that the next move will slide along the wall==================*/void P_HitSlideLine (line_t *ld){	int                     side;	angle_t         lineangle, moveangle, deltaangle;	fixed_t         movelen, newlen;	if (ld->slopetype == ST_HORIZONTAL)	{		tmymove = 0;		return;	}	if (ld->slopetype == ST_VERTICAL)	{		tmxmove = 0;		return;	}	side = P_PointOnLineSide (slidemo->x, slidemo->y, ld);	lineangle = R_PointToAngle2 (0,0, ld->dx, ld->dy);	if (side == 1)		lineangle += ANG180;	moveangle = R_PointToAngle2 (0,0, tmxmove, tmymove);	deltaangle = moveangle-lineangle;	if (deltaangle > ANG180)		deltaangle += ANG180;//              I_Error ("SlideLine: ang>ANG180");	lineangle >>= ANGLETOFINESHIFT;	deltaangle >>= ANGLETOFINESHIFT;	movelen = P_AproxDistance (tmxmove, tmymove);	newlen = FixedMul (movelen, finecosine[deltaangle]);	tmxmove = FixedMul (newlen, finecosine[lineangle]);	tmymove = FixedMul (newlen, finesine[lineangle]);}/*================ PTR_SlideTraverse===============*/boolean         PTR_SlideTraverse (intercept_t *in){	line_t  *li;	if (!in->isaline)		I_Error ("PTR_SlideTraverse: not a line?");	li = in->d.line;	if ( ! (li->flags & ML_TWOSIDED) )	{		if (P_PointOnLineSide (slidemo->x, slidemo->y, li))			return true;            // don't hit the back side		goto isblocking;	}	P_LineOpening (li);                  // set openrange, opentop, openbottom	if (openrange < slidemo->height)		goto isblocking;                // doesn't fit	if (opentop - slidemo->z < slidemo->height)		goto isblocking;                // mobj is too high	if (openbottom - slidemo->z > 24*FRACUNIT )		goto isblocking;                // too big a step up	return true;            // this line doesn't block movement// the line does block movement, see if it is closer than best so farisblocking:	if (in->frac < bestslidefrac)	{		secondslidefrac = bestslidefrac;		secondslideline = bestslideline;		bestslidefrac = in->frac;		bestslideline = li;	}	return false;   // stop}/*==================== P_SlideMove== The momx / momy move is bad, so try to slide along a wall== Find the first line hit, move flush to it, and slide along it== This is a kludgy mess.==================*/void P_SlideMove (mobj_t *mo){	fixed_t         leadx, leady;	fixed_t         trailx, traily;	fixed_t         newx, newy;	int                     hitcount;	slidemo = mo;	hitcount = 0;retry:	if (++hitcount == 3)		goto stairstep;                 // don't loop forever//// trace along the three leading corners//	if (mo->momx > 0)	{		leadx = mo->x + mo->radius;		trailx = mo->x - mo->radius;	}	else	{		leadx = mo->x - mo->radius;		trailx = mo->x + mo->radius;	}	if (mo->momy > 0)	{		leady = mo->y + mo->radius;		traily = mo->y - mo->radius;	}	else	{		leady = mo->y - mo->radius;		traily = mo->y + mo->radius;	}	bestslidefrac = FRACUNIT+1;	P_PathTraverse ( leadx, leady, leadx+mo->momx, leady+mo->momy,	 PT_ADDLINES, PTR_SlideTraverse );	P_PathTraverse ( trailx, leady, trailx+mo->momx, leady+mo->momy,	 PT_ADDLINES, PTR_SlideTraverse );	P_PathTraverse ( leadx, traily, leadx+mo->momx, traily+mo->momy,	 PT_ADDLINES, PTR_SlideTraverse );//// move up to the wall//	if(bestslidefrac == FRACUNIT+1)	{ // the move must have hit the middle, so stairstepstairstep:		if(!P_TryMove(mo, mo->x, mo->y+mo->momy))		{			P_TryMove(mo, mo->x+mo->momx, mo->y);		}		return;	}	bestslidefrac -= 0x800; // fudge a bit to make sure it doesn't hit	if (bestslidefrac > 0)	{		newx = FixedMul (mo->momx, bestslidefrac);		newy = FixedMul (mo->momy, bestslidefrac);		if (!P_TryMove (mo, mo->x+newx, mo->y+newy))			goto stairstep;	}//// now continue along the wall//	bestslidefrac = FRACUNIT-(bestslidefrac+0x800); // remainder	if (bestslidefrac > FRACUNIT)		bestslidefrac = FRACUNIT;	if (bestslidefrac <= 0)		return;	tmxmove = FixedMul (mo->momx, bestslidefrac);	tmymove = FixedMul (mo->momy, bestslidefrac);	P_HitSlideLine (bestslideline);                         // clip the moves	mo->momx = tmxmove;	mo->momy = tmymove;	if (!P_TryMove (mo, mo->x+tmxmove, mo->y+tmymove))	{		goto retry;	}}//============================================================================//// PTR_BounceTraverse////============================================================================boolean PTR_BounceTraverse(intercept_t *in){	line_t  *li;	if (!in->isaline)		I_Error ("PTR_BounceTraverse: not a line?");	li = in->d.line;	if (!(li->flags&ML_TWOSIDED))	{		if (P_PointOnLineSide (slidemo->x, slidemo->y, li))			return true;            // don't hit the back side		goto bounceblocking;	}	P_LineOpening (li);                  // set openrange, opentop, openbottom	if (openrange < slidemo->height)		goto bounceblocking;                // doesn't fit	if (opentop - slidemo->z < slidemo->height)		goto bounceblocking;                // mobj is too high	return true;            // this line doesn't block movement// the line does block movement, see if it is closer than best so farbounceblocking:	if (in->frac < bestslidefrac)	{		secondslidefrac = bestslidefrac;		secondslideline = bestslideline;		bestslidefrac = in->frac;		bestslideline = li;	}	return false;   // stop}//============================================================================//// P_BounceWall////============================================================================void P_BounceWall(mobj_t *mo){	fixed_t         leadx, leady;	int             side;	angle_t         lineangle, moveangle, deltaangle;	fixed_t         movelen;	slidemo = mo;//// trace along the three leading corners//	if(mo->momx > 0)	{		leadx = mo->x+mo->radius;	}	else	{		leadx = mo->x-mo->radius;	}	if(mo->momy > 0)	{		leady = mo->y+mo->radius;	}	else	{		leady = mo->y-mo->radius;	}	bestslidefrac = FRACUNIT+1;	P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy,		PT_ADDLINES, PTR_BounceTraverse);	side = P_PointOnLineSide(mo->x, mo->y, bestslideline);	lineangle = R_PointToAngle2(0, 0, bestslideline->dx,		bestslideline->dy);	if(side == 1)		lineangle += ANG180;	moveangle = R_PointToAngle2(0, 0, mo->momx, mo->momy);	deltaangle = (2*lineangle)-moveangle;//	if (deltaangle > ANG180)//		deltaangle += ANG180;//              I_Error ("SlideLine: ang>ANG180");	lineangle >>= ANGLETOFINESHIFT;	deltaangle >>= ANGLETOFINESHIFT;	movelen = P_AproxDistance(mo->momx, mo->momy);	movelen = FixedMul(movelen, 0.75*FRACUNIT); // friction	if (movelen < FRACUNIT) movelen = 2*FRACUNIT;	mo->momx = FixedMul(movelen, finecosine[deltaangle]);	mo->momy = FixedMul(movelen, finesine[deltaangle]);}/*==============================================================================							P_LineAttack==============================================================================*/mobj_t *PuffSpawned;mobj_t          *linetarget;                    // who got hit (or NULL)mobj_t          *shootthing;fixed_t         shootz;                                 // height if not aiming up or down									// ???: use slope for monsters?int                     la_damage;fixed_t         attackrange;fixed_t         aimslope;extern  fixed_t         topslope, bottomslope;  // slopes to top and bottom of target/*================================================================================= PTR_AimTraverse== Sets linetaget and aimslope when a target is aimed at===============================================================================*/boolean         PTR_AimTraverse (intercept_t *in){	line_t          *li;	mobj_t          *th;	fixed_t         slope, thingtopslope, thingbottomslope;	fixed_t         dist;	if (in->isaline)	{		li = in->d.line;		if ( !(li->flags & ML_TWOSIDED) )			return false;           // stop//// crosses a two sided line// a two sided line will restrict the possible target ranges		P_LineOpening (li);		if (openbottom >= opentop)			return false;           // stop		dist = FixedMul (attackrange, in->frac);		if (li->frontsector->floorheight != li->backsector->floorheight)		{			slope = FixedDiv (openbottom - shootz , dist);			if (slope > bottomslope)				bottomslope = slope;		}		if (li->frontsector->ceilingheight != li->backsector->ceilingheight)		{			slope = FixedDiv (opentop - shootz , dist);			if (slope < topslope)				topslope = slope;		}		if (topslope <= bottomslope)			return false;           // stop		return true;            // shot continues	}//// shoot a thing//	th = in->d.thing;	if (th == shootthing)		return true;            // can't shoot self	if(!(th->flags&MF_SHOOTABLE))	{ // corpse or something		return true;	}	if(th->player && netgame && !deathmatch)	{ // don't aim at fellow co-op players		return true;	}// check angles to see if the thing can be aimed at	dist = FixedMul (attackrange, in->frac);	thingtopslope = FixedDiv (th->z+th->height - shootz , dist);	if (thingtopslope < bottomslope)		return true;            // shot over the thing	thingbottomslope = FixedDiv (th->z - shootz, dist);	if (thingbottomslope > topslope)		return true;            // shot under the thing//// this thing can be hit!//	if (thingtopslope > topslope)		thingtopslope = topslope;	if (thingbottomslope < bottomslope)		thingbottomslope = bottomslope;	aimslope = (thingtopslope+thingbottomslope)/2;	linetarget = th;	return false;                   // don't go any farther}/*================================================================================ PTR_ShootTraverse===============================================================================*/boolean         PTR_ShootTraverse (intercept_t *in){	fixed_t         x,y,z;	fixed_t         frac;	line_t          *li;	mobj_t          *th;	fixed_t         slope;	fixed_t         dist;	fixed_t         thingtopslope, thingbottomslope;	extern mobj_t LavaInflictor;	if (in->isaline)	{		li = in->d.line;		if (li->special)		{			P_ActivateLine(li, shootthing, 0, SPAC_IMPACT);//			P_ShootSpecialLine (shootthing, li);		}		if ( !(li->flags & ML_TWOSIDED) )			goto hitline;//// crosses a two sided line//		P_LineOpening (li);		dist = FixedMul (attackrange, in->frac);		if (li->frontsector->floorheight != li->backsector->floorheight)		{			slope = FixedDiv (openbottom - shootz , dist);			if (slope > aimslope)				goto hitline;		}		if (li->frontsector->ceilingheight != li->backsector->ceilingheight)		{			slope = FixedDiv (opentop - shootz , dist);			if (slope < aimslope)				goto hitline;		}		return true;            // shot continues//// hit line//hitline:		// position a bit closer		frac = in->frac - FixedDiv (4*FRACUNIT,attackrange);		x = trace.x + FixedMul (trace.dx, frac);		y = trace.y + FixedMul (trace.dy, frac);		z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange));		if (li->frontsector->ceilingpic == skyflatnum)		{			if (z > li->frontsector->ceilingheight)				return false;           // don't shoot the sky!

⌨️ 快捷键说明

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