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

📄 p_map.c

📁 Nxdoom真的满好用的
💻 C
📖 第 1 页 / 共 2 页
字号:
// Emacs style mode select   -*- C++ -*- //-----------------------------------------------------------------------------//// $Id: p_map.c,v 1.2 2003/09/08 22:34:29 jasonk Exp $//// Copyright (C) 1993-1996 by id Software, Inc.//// This source is available for distribution and/or modification// only under the terms of the DOOM Source Code License as// published by id Software. All rights reserved.//// The source is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License// for more details.//// $Log: p_map.c,v $// Revision 1.2  2003/09/08 22:34:29  jasonk// Updated files because this fucker won't build for no fucking good reason.//// Revision 1.1.1.1  2003/09/04 21:08:13  jasonk// Initial import//// Revision 1.1  2000/12/08 21:07:53  jeffw// nxdoom initial entry -- No nxdoom/Makefile so it won't build automatically////// DESCRIPTION://	Movement, collision handling.//	Shooting and aiming.////-----------------------------------------------------------------------------static const charrcsid[] = "$Id: p_map.c,v 1.2 2003/09/08 22:34:29 jasonk Exp $";#include <stdlib.h>#include "m_bbox.h"#include "m_random.h"#include "i_system.h"#include "doomdef.h"#include "p_local.h"#include "s_sound.h"// State.#include "doomstat.h"#include "r_state.h"// Data.#include "sounds.h"fixed_t		tmbbox[4];mobj_t*		tmthing;int		tmflags;fixed_t		tmx;fixed_t		tmy;// If "floatok" true, move would be ok// if within "tmfloorz - tmceilingz".boolean		floatok;fixed_t		tmfloorz;fixed_t		tmceilingz;fixed_t		tmdropoffz;// 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;//// 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 )    {	// didn't hit it	return true;    }        // don't clip against self    if (thing == tmthing)	return true;        // monsters don't stomp things except on boss level    if ( !tmthing->player && gamemap != 30)	return false;			    P_DamageMobj (thing, tmthing, tmthing, 10000);	    return true;}//// P_TeleportMove//booleanP_TeleportMove( mobj_t*	thing,  fixed_t	x,  fixed_t	y ){    int			xl;    int			xh;    int			yl;    int			yh;    int			bx;    int			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;			    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;}//// 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)	return false;		// one sided line		    if (!(tmthing->flags & MF_MISSILE) )    {	if ( ld->flags & ML_BLOCKING )	    return false;	// explicitly blocking everything	if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS )	    return false;	// block monsters only    }    // set openrange, opentop, openbottom    P_LineOpening (ld);		    // adjust floor / ceiling heights    if (opentop < tmceilingz)    {	tmceilingz = opentop;	ceilingline = ld;    }    if (openbottom > tmfloorz)	tmfloorz = openbottom;	    if (lowfloor < tmdropoffz)	tmdropoffz = lowfloor;		    // if contacted a special line, add it to the list    if (ld->special)    {	spechit[numspechit] = ld;	numspechit++;    }    return true;}//// PIT_CheckThing//boolean PIT_CheckThing (mobj_t* thing){    fixed_t		blockdist;    boolean		solid;    int			damage;		    if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) ))	return true;        blockdist = thing->radius + tmthing->radius;    if ( abs(thing->x - tmx) >= blockdist	 || abs(thing->y - tmy) >= blockdist )    {	// didn't hit it	return true;	    }        // don't clip against self    if (thing == tmthing)	return true;        // check for skulls slamming into things    if (tmthing->flags & MF_SKULLFLY)    {	damage = ((P_Random()%8)+1)*tmthing->info->damage;		P_DamageMobj (thing, tmthing, tmthing, damage);		tmthing->flags &= ~MF_SKULLFLY;	tmthing->momx = tmthing->momy = tmthing->momz = 0;		P_SetMobjState (tmthing, tmthing->info->spawnstate);		return false;		// stop moving    }        // missiles can hit other things    if (tmthing->flags & MF_MISSILE)    {	// see if it went over / under	if (tmthing->z > thing->z + thing->height)	    return true;		// overhead	if (tmthing->z+tmthing->height < thing->z)	    return true;		// underneath			if (tmthing->target && (	    tmthing->target->type == thing->type || 	    (tmthing->target->type == MT_KNIGHT && thing->type == MT_BRUISER)||	    (tmthing->target->type == MT_BRUISER && thing->type == MT_KNIGHT) ) )	{	    // Don't hit same species as originator.	    if (thing == tmthing->target)		return true;	    if (thing->type != MT_PLAYER)	    {		// Explode, but do no damage.		// Let players missile other players.		return false;	    }	}		if (! (thing->flags & MF_SHOOTABLE) )	{	    // didn't do any damage	    return !(thing->flags & MF_SOLID);		}		// damage / explode	damage = ((P_Random()%8)+1)*tmthing->info->damage;	P_DamageMobj (thing, tmthing, tmthing->target, damage);	// don't traverse any more	return false;				    }        // check for special pickup    if (thing->flags & MF_SPECIAL)    {	solid = thing->flags&MF_SOLID;	if (tmflags&MF_PICKUP)	{	    // can remove thing	    P_TouchSpecialThing (thing, tmthing);	}	return !solid;    }	    return !(thing->flags & MF_SOLID);}//// MOVEMENT CLIPPING////// 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_PICKUP//  early out on solid lines?//// out://  newsubsec//  floorz//  ceilingz//  tmdropoffz//   the lowest point contacted//   (monsters won't move to a dropoff)//  speciallines[]//  numspeciallines//booleanP_CheckPosition( mobj_t*	thing,  fixed_t	x,  fixed_t	y ){    int			xl;    int			xh;    int			yl;    int			yh;    int			bx;    int			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;			    validcount++;    numspechit = 0;    if ( tmflags & MF_NOCLIP )	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;    for (bx=xl ; bx<=xh ; bx++)	for (by=yl ; by<=yh ; by++)	    if (!P_BlockThingsIterator(bx,by,PIT_CheckThing))		return false;        // check lines    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_TryMove// Attempt to move to a new position,// crossing special lines unless MF_TELEPORT is set.//booleanP_TryMove( mobj_t*	thing,  fixed_t	x,  fixed_t	y ){    fixed_t	oldx;    fixed_t	oldy;    int		side;    int		oldside;    line_t*	ld;    floatok = false;    if (!P_CheckPosition (thing, x, y))	return false;		// solid wall or thing        if ( !(thing->flags & MF_NOCLIP) )    {	if (tmceilingz - tmfloorz < thing->height)	    return false;	// doesn't fit	floatok = true;		if ( !(thing->flags&MF_TELEPORT) 	     &&tmceilingz - thing->z < thing->height)	    return false;	// mobj must lower itself to fit	if ( !(thing->flags&MF_TELEPORT)	     && tmfloorz - thing->z > 24*FRACUNIT )	    return false;	// too big a step up	if ( !(thing->flags&(MF_DROPOFF|MF_FLOAT))	     && tmfloorz - tmdropoffz > 24*FRACUNIT )	    return false;	// don't stand over a dropoff    }        // 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->x = x;    thing->y = y;    P_SetThingPosition (thing);        // if any special lines were hit, do the effect    if (! (thing->flags&(MF_TELEPORT|MF_NOCLIP)) )    {	while (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)		    P_CrossSpecialLine (ld-lines, oldside, thing);	    }	}    }    return true;}//// P_ThingHeightClip// Takes a valid thing and adjusts the thing->floorz,// thing->ceilingz, and 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;	    if (onfloor)    {	// walking monsters rise and fall with the floor	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 MOVE// Allows the player to slide along any angled walls.//fixed_t		bestslidefrac;fixed_t		secondslidefrac;line_t*		bestslideline;line_t*		secondslideline;mobj_t*		slidemo;fixed_t		tmxmove;fixed_t		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;    angle_t		moveangle;    angle_t		deltaangle;        fixed_t		movelen;    fixed_t		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))	{	    // don't hit the back side	    return true;			}	goto isblocking;    }    // set openrange, opentop, openbottom    P_LineOpening (li);        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

⌨️ 快捷键说明

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