From c137d2ad74b9b46c93411ce7fcae6d7041777d07 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sat, 6 Sep 2008 18:32:11 +0000 Subject: Move doom-specific files to a separate directory. Subversion-branch: /branches/raven-branch Subversion-revision: 1201 --- src/p_map.c | 1448 ----------------------------------------------------------- 1 file changed, 1448 deletions(-) delete mode 100644 src/p_map.c (limited to 'src/p_map.c') diff --git a/src/p_map.c b/src/p_map.c deleted file mode 100644 index 42f2a60f..00000000 --- a/src/p_map.c +++ /dev/null @@ -1,1448 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// Copyright(C) 1993-1996 Id Software, Inc. -// Copyright(C) 2005 Simon Howard, Andrey Budko -// -// This program is free software; you can redistribute it and/or -// modify it under the terms of the GNU General Public License -// as published by the Free Software Foundation; either version 2 -// of the License, or (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program; if not, write to the Free Software -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA -// 02111-1307, USA. -// -// DESCRIPTION: -// Movement, collision handling. -// Shooting and aiming. -// -//----------------------------------------------------------------------------- - - -#include - -#include "deh_misc.h" - -#include "m_bbox.h" -#include "m_random.h" -#include "i_system.h" - -#include "doomdef.h" -#include "m_argv.h" -#include "p_local.h" - -#include "s_sound.h" - -// State. -#include "doomstat.h" -#include "r_state.h" -// Data. -#include "sounds.h" - -// Spechit overrun magic value. -// -// This is the value used by PrBoom-plus. I think the value below is -// actually better and works with more demos. However, I think -// it's better for the spechits emulation to be compatible with -// PrBoom-plus, at least so that the big spechits emulation list -// on Doomworld can also be used with Chocolate Doom. - -#define DEFAULT_SPECHIT_MAGIC 0x01C09C98 - -// This is from a post by myk on the Doomworld forums, -// outputted from entryway's spechit_magic generator for -// s205n546.lmp. The _exact_ value of this isn't too -// important; as long as it is in the right general -// range, it will usually work. Otherwise, we can use -// the generator (hacked doom2.exe) and provide it -// with -spechit. - -//#define DEFAULT_SPECHIT_MAGIC 0x84f968e8 - - -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 walls -line_t* ceilingline; - -// keep track of special lines as they are hit, -// but don't process them until the move is proven valid - -// fraggle: I have increased the size of this buffer. In the original Doom, -// overrunning past this limit caused other bits of memory to be overwritten, -// affecting demo playback. However, in doing so, the limit was still -// exceeded. So we have to support more than 8 specials. -// -// We keep the original limit, to detect what variables in memory were -// overwritten (see SpechitOverrun()) - -#define MAXSPECIALCROSS 20 -#define MAXSPECIALCROSS_ORIGINAL 8 - -line_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 -// -boolean -P_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 -// - -static void SpechitOverrun(line_t *ld); - -// -// 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++; - - // fraggle: spechits overrun emulation code from prboom-plus - if (numspechit > MAXSPECIALCROSS_ORIGINAL) - { - SpechitOverrun(ld); - } - } - - 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; - - // sdh: Add deh_species_infighting here. We can override the - // "monsters of the same species cant hurt each other" behavior - // through dehacked patches - - if (thing->type != MT_PLAYER && !deh_species_infighting) - { - // 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 -// -boolean -P_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. -// -boolean -P_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 - - // this line doesn't block movement - return true; - - // the line does block movement, - // see if it is closer than best so far - isblocking: - 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; - fixed_t leady; - fixed_t trailx; - fixed_t traily; - fixed_t newx; - fixed_t 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 most have hit the middle, so stairstep - stairstep: - if (!P_TryMove (mo, mo->x, mo->y + mo->momy)) - P_TryMove (mo, mo->x + mo->momx, mo->y); - return; - } - - // fudge a bit to make sure it doesn't hit - bestslidefrac -= 0x800; - 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. - // First calculate remainder. - bestslidefrac = FRACUNIT-(bestslidefrac+0x800); - - 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; - } -} - - -// -// P_LineAttack -// -mobj_t* linetarget; // who got hit (or NULL) -mobj_t* shootthing; - -// Height if not aiming up or down -// ???: use slope for monsters? -fixed_t shootz; - -int la_damage; -fixed_t attackrange; - -fixed_t aimslope; - -// slopes to top and bottom of target -extern fixed_t topslope; -extern fixed_t bottomslope; - - -// -// 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; - fixed_t thingtopslope; - fixed_t 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)) - return true; // corpse or something - - // 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; - fixed_t y; - fixed_t z; - fixed_t frac; - - line_t* li; - - mobj_t* th; - - fixed_t slope; - fixed_t dist; - fixed_t thingtopslope; - fixed_t thingbottomslope; - - if (in->isaline) - { - li = in->d.line; - - if (li->special) - 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; - } - - // shot continues - return true; - - - // 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) - { - // don't shoot the sky! - if (z > li->frontsector->ceilingheight) - return false; - - // it's a sky hack wall - if (li->backsector && li->backsector->ceilingpic == skyflatnum) - return false; - } - - // Spawn bullet puffs. - P_SpawnPuff (x,y,z); - - // don't go any farther - return false; - } - - // shoot a thing - th = in->d.thing; - if (th == shootthing) - return true; // can't shoot self - - if (!(th->flags&MF_SHOOTABLE)) - return true; // corpse or something - - // 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 < aimslope) - return true; // shot over the thing - - thingbottomslope = FixedDiv (th->z - shootz, dist); - - if (thingbottomslope > aimslope) - return true; // shot under the thing - - - // hit thing - // position a bit closer - frac = in->frac - FixedDiv (10*FRACUNIT,attackrange); - - x = trace.x + FixedMul (trace.dx, frac); - y = trace.y + FixedMul (trace.dy, frac); - z = shootz + FixedMul (aimslope, FixedMul(frac, attackrange)); - - // Spawn bullet puffs or blod spots, - // depending on target type. - if (in->d.thing->flags & MF_NOBLOOD) - P_SpawnPuff (x,y,z); - else - P_SpawnBlood (x,y,z, la_damage); - - if (la_damage) - P_DamageMobj (th, shootthing, shootthing, la_damage); - - // don't go any farther - return false; - -} - - -// -// P_AimLineAttack -// -fixed_t -P_AimLineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance ) -{ - fixed_t x2; - fixed_t y2; - - t1 = P_SubstNullMobj(t1); - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - - // can't shoot outside view angles - topslope = 100*FRACUNIT/160; - bottomslope = -100*FRACUNIT/160; - - attackrange = distance; - linetarget = NULL; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_AimTraverse ); - - if (linetarget) - return aimslope; - - return 0; -} - - -// -// P_LineAttack -// If damage == 0, it is just a test trace -// that will leave linetarget set. -// -void -P_LineAttack -( mobj_t* t1, - angle_t angle, - fixed_t distance, - fixed_t slope, - int damage ) -{ - fixed_t x2; - fixed_t y2; - - angle >>= ANGLETOFINESHIFT; - shootthing = t1; - la_damage = damage; - x2 = t1->x + (distance>>FRACBITS)*finecosine[angle]; - y2 = t1->y + (distance>>FRACBITS)*finesine[angle]; - shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; - attackrange = distance; - aimslope = slope; - - P_PathTraverse ( t1->x, t1->y, - x2, y2, - PT_ADDLINES|PT_ADDTHINGS, - PTR_ShootTraverse ); -} - - - -// -// USE LINES -// -mobj_t* usething; - -boolean PTR_UseTraverse (intercept_t* in) -{ - int side; - - if (!in->d.line->special) - { - P_LineOpening (in->d.line); - if (openrange <= 0) - { - S_StartSound (usething, sfx_noway); - - // can't use through a wall - return false; - } - // not a special line, but keep checking - return true ; - } - - side = 0; - if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1) - side = 1; - - // return false; // don't use back side - - P_UseSpecialLine (usething, in->d.line, side); - - // can't use for than one special line in a row - return false; -} - - -// -// P_UseLines -// Looks for special lines in front of the player to activate. -// -void P_UseLines (player_t* player) -{ - int angle; - fixed_t x1; - fixed_t y1; - fixed_t x2; - fixed_t y2; - - usething = player->mo; - - angle = player->mo->angle >> ANGLETOFINESHIFT; - - x1 = player->mo->x; - y1 = player->mo->y; - x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; - y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; - - P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTraverse ); -} - - -// -// RADIUS ATTACK -// -mobj_t* bombsource; -mobj_t* bombspot; -int bombdamage; - - -// -// PIT_RadiusAttack -// "bombsource" is the creature -// that caused the explosion at "bombspot". -// -boolean PIT_RadiusAttack (mobj_t* thing) -{ - fixed_t dx; - fixed_t dy; - fixed_t dist; - - if (!(thing->flags & MF_SHOOTABLE) ) - return true; - - // Boss spider and cyborg - // take no damage from concussion. - if (thing->type == MT_CYBORG - || thing->type == MT_SPIDER) - return true; - - dx = abs(thing->x - bombspot->x); - dy = abs(thing->y - bombspot->y); - - dist = dx>dy ? dx : dy; - dist = (dist - thing->radius) >> FRACBITS; - - if (dist < 0) - dist = 0; - - if (dist >= bombdamage) - return true; // out of range - - if ( P_CheckSight (thing, bombspot) ) - { - // must be in direct path - P_DamageMobj (thing, bombspot, bombsource, bombdamage - dist); - } - - return true; -} - - -// -// P_RadiusAttack -// Source is the creature that caused the explosion at spot. -// -void -P_RadiusAttack -( mobj_t* spot, - mobj_t* source, - int damage ) -{ - int x; - int y; - - int xl; - int xh; - int yl; - int yh; - - fixed_t dist; - - dist = (damage+MAXRADIUS)<y + dist - bmaporgy)>>MAPBLOCKSHIFT; - yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; - xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; - xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; - bombspot = spot; - bombsource = source; - bombdamage = damage; - - for (y=yl ; y<=yh ; y++) - for (x=xl ; x<=xh ; x++) - P_BlockThingsIterator (x, y, PIT_RadiusAttack ); -} - - - -// -// 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; - - -// -// PIT_ChangeSector -// -boolean PIT_ChangeSector (mobj_t* thing) -{ - mobj_t* mo; - - if (P_ThingHeightClip (thing)) - { - // keep checking - return true; - } - - - // crunch bodies to giblets - if (thing->health <= 0) - { - P_SetMobjState (thing, S_GIBS); - - thing->flags &= ~MF_SOLID; - thing->height = 0; - thing->radius = 0; - - // keep checking - return true; - } - - // crunch dropped items - if (thing->flags & MF_DROPPED) - { - P_RemoveMobj (thing); - - // keep checking - return true; - } - - if (! (thing->flags & MF_SHOOTABLE) ) - { - // assume it is bloody gibs or something - return true; - } - - nofit = true; - - if (crushchange && !(leveltime&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; - } - - // keep checking (crush other things) - return true; -} - - - -// -// P_ChangeSector -// -boolean -P_ChangeSector -( sector_t* sector, - boolean crunch ) -{ - int x; - int y; - - nofit = false; - crushchange = crunch; - - // re-check 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; -} - -// Code to emulate the behavior of Vanilla Doom when encountering an overrun -// of the spechit array. This is by Andrey Budko (e6y) and comes from his -// PrBoom plus port. A big thanks to Andrey for this. - -static void SpechitOverrun(line_t *ld) -{ - static unsigned int baseaddr = 0; - unsigned int addr; - - if (baseaddr == 0) - { - int p; - - // This is the first time we have had an overrun. Work out - // what base address we are going to use. - // Allow a spechit value to be specified on the command line. - - //! - // @category compat - // @arg - // - // Use the specified magic value when emulating spechit overruns. - // - - p = M_CheckParm("-spechit"); - - if (p > 0) - { - baseaddr = atoi(myargv[p+1]); - } - else - { - baseaddr = DEFAULT_SPECHIT_MAGIC; - } - } - - // Calculate address used in doom2.exe - - addr = baseaddr + (ld - lines) * 0x3E; - - switch(numspechit) - { - case 9: - case 10: - case 11: - case 12: - tmbbox[numspechit-9] = addr; - break; - case 13: - crushchange = addr; - break; - case 14: - nofit = addr; - break; - default: - fprintf(stderr, "SpechitOverrun: Warning: unable to emulate" - "an overrun where numspechit=%i\n", - numspechit); - break; - } -} - -- cgit v1.2.3