Source to src/p_change.c


Enter a symbol's name here to quickly find it.

/* p_change.c */

#include "doomdef.h"
#include "p_local.h"

/* 
============================================================================== 

						SECTOR HEIGHT CHANGING

= After modifying a sectors floor or ceiling height, call this
= routine to adjust the positions of all things that touch the
= sector.
=
= If anything doesn't fit anymore, true will be returned.
= If crunch is true, they will take damage as they are being crushed
= If Crunch is false, you should set the sector height back the way it
= was and call P_ChangeSector again to undo the changes
============================================================================== 
*/ 
 
boolean		crushchange;
boolean		nofit;

/*
==================
=
= 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;
	
	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;
}


/*
===============
=
= PIT_ChangeSector
=
===============
*/

boolean PIT_ChangeSector (mobj_t *thing)
{
	mobj_t		*mo;
	
	if (P_ThingHeightClip (thing))
		return true;		/* keep checking */

	/* crunch bodies to giblets */
	if (thing->health <= 0)
	{
		P_SetMobjState (thing, S_GIBS);
		thing->height = 0;
		thing->radius = 0;
		return true;		/* keep checking */
	}

	/* crunch dropped items */
	if (thing->flags & MF_DROPPED)
	{
		P_RemoveMobj (thing);
		return true;		/* keep checking */
	}

	if (! (thing->flags & MF_SHOOTABLE) )
		return true;				/* assume it is bloody gibs or something */
		
	nofit = true;
	if (crushchange && !(gametic&3) )
	{
		P_DamageMobj(thing,NULL,NULL,10);
		/* spray blood in a random direction */
		mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD);
		mo->momx = (P_Random() - P_Random ())<<12;
		mo->momy = (P_Random() - P_Random ())<<12;
	}
		
	return true;		/* keep checking (crush other things)	 */
}

/*
===============
=
= P_ChangeSector
=
===============
*/

boolean P_ChangeSector (sector_t *sector, boolean crunch)
{
	int			x,y;
	int			i;
	
/* force next sound to reflood */
	for (i=0 ; i<MAXPLAYERS ; i++)
		players[i].lastsoundsector = NULL;
		
	nofit = false;
	crushchange = crunch;
	
/* recheck heights for all things near the moving sector */

	for (x=sector->blockbox[BOXLEFT] ; x<= sector->blockbox[BOXRIGHT] ; x++)
		for (y=sector->blockbox[BOXBOTTOM];y<= sector->blockbox[BOXTOP] ; y++)
			P_BlockThingsIterator (x, y, PIT_ChangeSector);
	
	
	return nofit;
}