mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-27 22:42:57 +00:00
- Replaced P_PathTraverse with an FPathTraverse class, rewrote all code using
P_PathTraverse and got rid of a lot of global variables in the process. SVN r898 (trunk)
This commit is contained in:
parent
a0356a45cd
commit
a390ea6a61
10 changed files with 1013 additions and 1006 deletions
|
@ -1,3 +1,11 @@
|
|||
April 9, 2008 (Changes by Graf Zahl)
|
||||
- Replaced P_PathTraverse with an FPathTraverse class, rewrote all code using
|
||||
P_PathTraverse and got rid of a lot of global variables in the process.
|
||||
- Simplified the use of the checkarray in FBlockThingsIterator: Since the entire
|
||||
game runs single threaded there is no need for multiple check arrays if
|
||||
recursive use occurs. Using the same array with a higher start index is
|
||||
sufficient if the size is reset after finishing using the iterator.
|
||||
|
||||
April 9, 2008 (SBarInfo Update #17)
|
||||
- Fixed: SBarInfo tried to calculate scaled offsets on unscaled status bars.
|
||||
- Added: createpopup to SBarInfo. No we don't have custom popups yet. It only
|
||||
|
|
|
@ -25,16 +25,28 @@
|
|||
|
||||
static FRandom pr_botdofire ("BotDoFire");
|
||||
|
||||
//Used with Reachable().
|
||||
static AActor *looker;
|
||||
static AActor *rtarget;
|
||||
static bool reachable;
|
||||
static fixed_t last_z;
|
||||
static sector_t *last_s;
|
||||
static fixed_t estimated_dist;
|
||||
|
||||
static bool PTR_Reachable (intercept_t *in)
|
||||
//Checks TRUE reachability from
|
||||
//one looker to another. First mobj (looker) is looker.
|
||||
bool FCajunMaster::Reachable (AActor *looker, AActor *rtarget)
|
||||
{
|
||||
if (looker == rtarget)
|
||||
return false;
|
||||
|
||||
if ((rtarget->Sector->ceilingplane.ZatPoint (rtarget->x, rtarget->y) -
|
||||
rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y))
|
||||
< looker->height) //Where rtarget is, looker can't be.
|
||||
return false;
|
||||
|
||||
sector_t *last_s = looker->Sector;
|
||||
fixed_t last_z = last_s->floorplane.ZatPoint (looker->x, looker->y);
|
||||
fixed_t estimated_dist = P_AproxDistance (looker->x - rtarget->x, looker->y - rtarget->y);
|
||||
bool reachable = true;
|
||||
|
||||
FPathTraverse it(looker->x+looker->momx, looker->y+looker->momy, rtarget->x, rtarget->y, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
fixed_t hitx, hity;
|
||||
fixed_t frac;
|
||||
line_t *line;
|
||||
|
@ -45,8 +57,8 @@ static bool PTR_Reachable (intercept_t *in)
|
|||
frac = in->frac - FixedDiv (4*FRACUNIT, MAX_TRAVERSE_DIST);
|
||||
dist = FixedMul (frac, MAX_TRAVERSE_DIST);
|
||||
|
||||
hitx = trace.x + FixedMul (looker->momx, frac);
|
||||
hity = trace.y + FixedMul (looker->momy, frac);
|
||||
hitx = it.Trace().x + FixedMul (looker->momx, frac);
|
||||
hity = it.Trace().y + FixedMul (looker->momy, frac);
|
||||
|
||||
if (in->isaline)
|
||||
{
|
||||
|
@ -54,7 +66,7 @@ static bool PTR_Reachable (intercept_t *in)
|
|||
|
||||
if (!(line->flags & ML_TWOSIDED) || (line->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)))
|
||||
{
|
||||
return (reachable = false); //Cannot continue.
|
||||
return false; //Cannot continue.
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -70,53 +82,30 @@ static bool PTR_Reachable (intercept_t *in)
|
|||
{
|
||||
last_z = floorheight;
|
||||
last_s = s;
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (reachable = false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dist > estimated_dist)
|
||||
{
|
||||
reachable = true;
|
||||
return false; //Don't need to continue.
|
||||
return true;
|
||||
}
|
||||
|
||||
thing = in->d.thing;
|
||||
if (thing == looker) //Can't reach self in this case.
|
||||
return true;
|
||||
continue;
|
||||
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y) <= (last_z+MAXMOVEHEIGHT)))
|
||||
{
|
||||
reachable = true;
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
reachable = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Checks TRUE reachability from
|
||||
//one actor to another. First mobj (actor) is looker.
|
||||
bool FCajunMaster::Reachable (AActor *actor, AActor *target)
|
||||
{
|
||||
if (actor == target)
|
||||
return false;
|
||||
|
||||
if ((target->Sector->ceilingplane.ZatPoint (target->x, target->y) -
|
||||
target->Sector->floorplane.ZatPoint (target->x, target->y))
|
||||
< actor->height) //Where target is, looker can't be.
|
||||
return false;
|
||||
|
||||
looker = actor;
|
||||
rtarget = target;
|
||||
last_s = actor->Sector;
|
||||
last_z = last_s->floorplane.ZatPoint (actor->x, actor->y);
|
||||
reachable = true;
|
||||
estimated_dist = P_AproxDistance (actor->x - target->x, actor->y - target->y);
|
||||
P_PathTraverse (actor->x+actor->momx, actor->y+actor->momy, target->x, target->y, PT_ADDLINES|PT_ADDTHINGS, PTR_Reachable);
|
||||
}
|
||||
return reachable;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,59 @@ void FBoundingBox::AddToBox (fixed_t x, fixed_t y)
|
|||
m_Box[BOXTOP] = y;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FBoundingBox :: BoxOnLineSide
|
||||
//
|
||||
// Considers the line to be infinite
|
||||
// Returns side 0 or 1, -1 if box crosses the line.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int FBoundingBox::BoxOnLineSide (const line_t *ld) const
|
||||
{
|
||||
return P_BoxOnLineSide(m_Box, ld);
|
||||
int p1;
|
||||
int p2;
|
||||
|
||||
switch (ld->slopetype)
|
||||
{
|
||||
case ST_HORIZONTAL:
|
||||
p1 = m_Box[BOXTOP] > ld->v1->y;
|
||||
p2 = m_Box[BOXBOTTOM] > ld->v1->y;
|
||||
if (ld->dx < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_VERTICAL:
|
||||
p1 = m_Box[BOXRIGHT] < ld->v1->x;
|
||||
p2 = m_Box[BOXLEFT] < ld->v1->x;
|
||||
if (ld->dy < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_POSITIVE:
|
||||
p1 = P_PointOnLineSide (m_Box[BOXLEFT], m_Box[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (m_Box[BOXRIGHT], m_Box[BOXBOTTOM], ld);
|
||||
break;
|
||||
|
||||
case ST_NEGATIVE:
|
||||
default: // Just to assure GCC that p1 and p2 really do get initialized
|
||||
p1 = P_PointOnLineSide (m_Box[BOXRIGHT], m_Box[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (m_Box[BOXLEFT], m_Box[BOXBOTTOM], ld);
|
||||
break;
|
||||
}
|
||||
|
||||
return (p1 == p2) ? p1 : -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -160,6 +160,7 @@ typedef struct
|
|||
{
|
||||
fixed_t frac; // along trace line
|
||||
bool isaline;
|
||||
bool done;
|
||||
union {
|
||||
AActor *thing;
|
||||
line_t *line;
|
||||
|
@ -215,7 +216,6 @@ inline void P_MakeDivline (const line_t *li, divline_t *dl)
|
|||
}
|
||||
|
||||
fixed_t P_InterceptVector (const divline_t *v2, const divline_t *v1);
|
||||
int P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld);
|
||||
|
||||
struct FLineOpening
|
||||
{
|
||||
|
@ -255,10 +255,7 @@ public:
|
|||
|
||||
class FBlockThingsIterator
|
||||
{
|
||||
typedef TArray<AActor *> BTChecked;
|
||||
|
||||
static TDeletingArray< BTChecked* > FreeBTChecked;
|
||||
|
||||
static TArray<AActor *> CheckArray;
|
||||
|
||||
int minx, maxx;
|
||||
int miny, maxy;
|
||||
|
@ -266,21 +263,24 @@ class FBlockThingsIterator
|
|||
int curx, cury;
|
||||
|
||||
bool dontfreecheck;
|
||||
BTChecked *checkarray;
|
||||
int checkindex;
|
||||
|
||||
FBlockNode *block;
|
||||
|
||||
BTChecked *GetCheckArray();
|
||||
void FreeCheckArray();
|
||||
void StartBlock(int x, int y);
|
||||
|
||||
// The following 3 functions are only for use in the path traverser
|
||||
// and therefore declared private.
|
||||
static int GetCheckIndex();
|
||||
static void SetCheckIndex(int newvalue);
|
||||
FBlockThingsIterator(int x, int y, int checkindex);
|
||||
|
||||
friend class FPathTraverse;
|
||||
|
||||
public:
|
||||
FBlockThingsIterator(int minx, int miny, int maxx, int maxy, TArray<AActor *> *check = NULL);
|
||||
FBlockThingsIterator(int minx, int miny, int maxx, int maxy);
|
||||
FBlockThingsIterator(const FBoundingBox &box);
|
||||
~FBlockThingsIterator()
|
||||
{
|
||||
if (!dontfreecheck) FreeCheckArray();
|
||||
}
|
||||
~FBlockThingsIterator();
|
||||
AActor *Next();
|
||||
void Reset() { StartBlock(minx, miny); }
|
||||
};
|
||||
|
@ -293,20 +293,31 @@ public:
|
|||
AActor *Next();
|
||||
};
|
||||
|
||||
class FPathTraverse
|
||||
{
|
||||
static TArray<intercept_t> intercepts;
|
||||
|
||||
divline_t trace;
|
||||
unsigned int intercept_index;
|
||||
unsigned int intercept_count;
|
||||
fixed_t maxfrac;
|
||||
unsigned int count;
|
||||
|
||||
void AddLineIntercepts(int bx, int by);
|
||||
void AddThingIntercepts(int bx, int by, int checkindex);
|
||||
public:
|
||||
|
||||
intercept_t *Next();
|
||||
|
||||
FPathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags);
|
||||
~FPathTraverse();
|
||||
const divline_t &Trace() const { return trace; }
|
||||
};
|
||||
|
||||
|
||||
#define PT_ADDLINES 1
|
||||
#define PT_ADDTHINGS 2
|
||||
|
||||
extern divline_t trace;
|
||||
|
||||
bool
|
||||
P_PathTraverse
|
||||
( fixed_t x1,
|
||||
fixed_t y1,
|
||||
fixed_t x2,
|
||||
fixed_t y2,
|
||||
int flags,
|
||||
bool (*trav) (intercept_t *));
|
||||
|
||||
AActor *P_BlockmapSearch (AActor *origin, int distance, AActor *(*func)(AActor *, int));
|
||||
AActor *P_RoughMonsterSearch (AActor *mo, int distance);
|
||||
|
||||
|
@ -385,9 +396,7 @@ bool P_CheckMissileSpawn (AActor *missile);
|
|||
void P_PlaySpawnSound(AActor *missile, AActor *spawner);
|
||||
|
||||
// [RH] Position the chasecam
|
||||
void P_AimCamera (AActor *t1);
|
||||
extern fixed_t CameraX, CameraY, CameraZ;
|
||||
extern sector_t *CameraSector;
|
||||
void P_AimCamera (AActor *t1, fixed_t &x, fixed_t &y, fixed_t &z, sector_t *&sec);
|
||||
|
||||
// [RH] Means of death
|
||||
void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, bool hurtSelf, bool dodamage=true);
|
||||
|
|
452
src/p_map.cpp
452
src/p_map.cpp
|
@ -60,16 +60,13 @@
|
|||
#define WATER_SINK_SPEED (FRACUNIT/2)
|
||||
#define WATER_JUMP_SPEED (FRACUNIT*7/2)
|
||||
|
||||
#define USE_PUZZLE_ITEM_SPECIAL 129
|
||||
|
||||
|
||||
CVAR (Bool, cl_bloodsplats, true, CVAR_ARCHIVE)
|
||||
CVAR (Int, sv_smartaim, 0, CVAR_ARCHIVE|CVAR_SERVERINFO)
|
||||
|
||||
static void CheckForPushSpecial (line_t *line, int side, AActor *mobj);
|
||||
static void SpawnShootDecal (AActor *t1, const FTraceResults &trace);
|
||||
static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff,
|
||||
fixed_t vx, fixed_t vy, fixed_t vz);
|
||||
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz);
|
||||
|
||||
static FRandom pr_tracebleed ("TraceBleed");
|
||||
static FRandom pr_checkthing ("CheckThing");
|
||||
|
@ -1654,18 +1651,28 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
|||
// SLIDE MOVE
|
||||
// Allows the player to slide along any angled walls.
|
||||
//
|
||||
fixed_t bestslidefrac;
|
||||
fixed_t secondslidefrac;
|
||||
struct FSlide
|
||||
{
|
||||
fixed_t bestslidefrac;
|
||||
fixed_t secondslidefrac;
|
||||
|
||||
line_t* bestslideline;
|
||||
line_t* secondslideline;
|
||||
line_t* bestslideline;
|
||||
line_t* secondslideline;
|
||||
|
||||
AActor* slidemo;
|
||||
AActor* slidemo;
|
||||
|
||||
fixed_t tmxmove;
|
||||
fixed_t tmymove;
|
||||
fixed_t tmxmove;
|
||||
fixed_t tmymove;
|
||||
|
||||
void HitSlideLine(line_t *ld);
|
||||
void SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
|
||||
void SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps);
|
||||
|
||||
// The bouncing code uses the same data structure
|
||||
bool BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
|
||||
bool BounceWall (AActor *mo);
|
||||
};
|
||||
|
||||
extern bool onground;
|
||||
|
||||
|
||||
//
|
||||
|
@ -1674,7 +1681,7 @@ extern bool onground;
|
|||
// so that the next move will slide along the wall.
|
||||
// If the floor is icy, then you can bounce off a wall. // phares
|
||||
//
|
||||
void P_HitSlideLine (line_t* ld)
|
||||
void FSlide::HitSlideLine (line_t* ld)
|
||||
{
|
||||
int side;
|
||||
|
||||
|
@ -1810,21 +1817,30 @@ void P_HitSlideLine (line_t* ld)
|
|||
//
|
||||
// PTR_SlideTraverse
|
||||
//
|
||||
bool PTR_SlideTraverse (intercept_t* in)
|
||||
void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
|
||||
{
|
||||
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
line_t* li;
|
||||
|
||||
if (!in->isaline)
|
||||
I_Error ("PTR_SlideTraverse: not a line?");
|
||||
{
|
||||
// should never happen
|
||||
Printf ("PTR_SlideTraverse: not a line?");
|
||||
continue;
|
||||
}
|
||||
|
||||
li = in->d.line;
|
||||
|
||||
if ( !(li->flags & ML_TWOSIDED) )
|
||||
if ( !(li->flags & ML_TWOSIDED) || !li->backsector )
|
||||
{
|
||||
if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
|
||||
{
|
||||
// don't hit the back side
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
goto isblocking;
|
||||
}
|
||||
|
@ -1843,8 +1859,8 @@ bool PTR_SlideTraverse (intercept_t* in)
|
|||
|
||||
FLineOpening open;
|
||||
// set openrange, opentop, openbottom
|
||||
P_LineOpening (open, slidemo, li, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
P_LineOpening (open, slidemo, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
|
||||
if (open.range < slidemo->height)
|
||||
goto isblocking; // doesn't fit
|
||||
|
@ -1869,7 +1885,7 @@ bool PTR_SlideTraverse (intercept_t* in)
|
|||
}
|
||||
|
||||
// this line doesn't block movement
|
||||
return true;
|
||||
continue;
|
||||
|
||||
// the line does block movement,
|
||||
// see if it is closer than best so far
|
||||
|
@ -1882,7 +1898,8 @@ bool PTR_SlideTraverse (intercept_t* in)
|
|||
bestslideline = li;
|
||||
}
|
||||
|
||||
return false; // stop
|
||||
return; // stop
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1896,7 +1913,7 @@ bool PTR_SlideTraverse (intercept_t* in)
|
|||
//
|
||||
// This is a kludgy mess.
|
||||
//
|
||||
void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
||||
void FSlide::SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
||||
{
|
||||
fixed_t leadx, leady;
|
||||
fixed_t trailx, traily;
|
||||
|
@ -1905,8 +1922,8 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
bool walkplane;
|
||||
int hitcount;
|
||||
|
||||
slidemo = mo;
|
||||
hitcount = 3;
|
||||
slidemo = mo;
|
||||
|
||||
if (mo->player && mo->reactiontime > 0)
|
||||
return; // player coming right out of a teleporter.
|
||||
|
@ -1940,9 +1957,9 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
|
||||
bestslidefrac = FRACUNIT+1;
|
||||
|
||||
P_PathTraverse (leadx, leady, leadx+tryx, leady+tryy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse (trailx, leady, trailx+tryx, leady+tryy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
P_PathTraverse (leadx, traily, leadx+tryx, traily+tryy, PT_ADDLINES, PTR_SlideTraverse);
|
||||
SlideTraverse (leadx, leady, leadx+tryx, leady+tryy);
|
||||
SlideTraverse (trailx, leady, trailx+tryx, leady+tryy);
|
||||
SlideTraverse (leadx, traily, leadx+tryx, traily+tryy);
|
||||
|
||||
// move up to the wall
|
||||
if (bestslidefrac == FRACUNIT+1)
|
||||
|
@ -1983,7 +2000,7 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
tryx = tmxmove = FixedMul (tryx, bestslidefrac);
|
||||
tryy = tmymove = FixedMul (tryy, bestslidefrac);
|
||||
|
||||
P_HitSlideLine (bestslideline); // clip the moves
|
||||
HitSlideLine (bestslideline); // clip the moves
|
||||
|
||||
mo->momx = tmxmove * numsteps;
|
||||
mo->momy = tmymove * numsteps;
|
||||
|
@ -2006,6 +2023,11 @@ void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
|||
}
|
||||
}
|
||||
|
||||
void P_SlideMove (AActor *mo, fixed_t tryx, fixed_t tryy, int numsteps)
|
||||
{
|
||||
FSlide slide;
|
||||
slide.SlideMove(mo, tryx, tryy, numsteps);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -2110,12 +2132,21 @@ bool P_CheckSlopeWalk (AActor *actor, fixed_t &xmove, fixed_t &ymove)
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
bool PTR_BounceTraverse (intercept_t *in)
|
||||
bool FSlide::BounceTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
|
||||
{
|
||||
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
|
||||
line_t *li;
|
||||
|
||||
if (!in->isaline)
|
||||
I_Error ("PTR_BounceTraverse: not a line?");
|
||||
{
|
||||
Printf ("PTR_BounceTraverse: not a line?");
|
||||
continue;
|
||||
}
|
||||
|
||||
li = in->d.line;
|
||||
assert(((size_t)li - (size_t)lines) % sizeof(line_t) == 0);
|
||||
|
@ -2123,17 +2154,17 @@ bool PTR_BounceTraverse (intercept_t *in)
|
|||
{
|
||||
goto bounceblocking;
|
||||
}
|
||||
if (!(li->flags&ML_TWOSIDED))
|
||||
if (!(li->flags&ML_TWOSIDED) || !li->backsector)
|
||||
{
|
||||
if (P_PointOnLineSide (slidemo->x, slidemo->y, li))
|
||||
return true; // don't hit the back side
|
||||
continue; // don't hit the back side
|
||||
goto bounceblocking;
|
||||
}
|
||||
|
||||
FLineOpening open;
|
||||
|
||||
P_LineOpening (open, slidemo, li, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac)); // set openrange, opentop, openbottom
|
||||
P_LineOpening (open, slidemo, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac)); // set openrange, opentop, openbottom
|
||||
if (open.range < slidemo->height)
|
||||
goto bounceblocking; // doesn't fit
|
||||
|
||||
|
@ -2143,10 +2174,10 @@ bool PTR_BounceTraverse (intercept_t *in)
|
|||
if (open.bottom > slidemo->z)
|
||||
goto bounceblocking; // mobj is too low
|
||||
|
||||
return true; // this line doesn't block movement
|
||||
continue; // this line doesn't block movement
|
||||
|
||||
// the line does block movement, see if it is closer than best so far
|
||||
bounceblocking:
|
||||
// the line does block movement, see if it is closer than best so far
|
||||
bounceblocking:
|
||||
if (in->frac < bestslidefrac)
|
||||
{
|
||||
secondslidefrac = bestslidefrac;
|
||||
|
@ -2155,6 +2186,8 @@ bounceblocking:
|
|||
bestslideline = li;
|
||||
}
|
||||
return false; // stop
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -2163,7 +2196,7 @@ bounceblocking:
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
bool P_BounceWall (AActor *mo)
|
||||
bool FSlide::BounceWall (AActor *mo)
|
||||
{
|
||||
fixed_t leadx, leady;
|
||||
int side;
|
||||
|
@ -2198,8 +2231,7 @@ bool P_BounceWall (AActor *mo)
|
|||
}
|
||||
bestslidefrac = FRACUNIT+1;
|
||||
bestslideline = mo->BlockingLine;
|
||||
if (P_PathTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy,
|
||||
PT_ADDLINES, PTR_BounceTraverse) && mo->BlockingLine == NULL)
|
||||
if (BounceTraverse(leadx, leady, leadx+mo->momx, leady+mo->momy) && mo->BlockingLine == NULL)
|
||||
{ // Could not find a wall, so bounce off the floor/ceiling instead.
|
||||
fixed_t floordist = mo->z - mo->floorz;
|
||||
fixed_t ceildist = mo->ceilingz - mo->z;
|
||||
|
@ -2246,15 +2278,11 @@ bool P_BounceWall (AActor *mo)
|
|||
movelen = P_AproxDistance (mo->momx, mo->momy);
|
||||
movelen = (movelen * 192) >> 8; // friction
|
||||
|
||||
fixed_t box[4];
|
||||
box[BOXTOP] = mo->y + mo->radius;
|
||||
box[BOXBOTTOM] = mo->y - mo->radius;
|
||||
box[BOXLEFT] = mo->x - mo->radius;
|
||||
box[BOXRIGHT] = mo->x + mo->radius;
|
||||
if (P_BoxOnLineSide (box, line) == -1)
|
||||
FBoundingBox box(mo->x, mo->y, mo->radius);
|
||||
if (box.BoxOnLineSide (line) == -1)
|
||||
{
|
||||
mo->SetOrigin (mo->x + FixedMul(mo->radius,
|
||||
finecosine[deltaangle]), mo->y + FixedMul(mo->radius, finesine[deltaangle]), mo->z);;
|
||||
finecosine[deltaangle]), mo->y + FixedMul(mo->radius, finesine[deltaangle]), mo->z);
|
||||
}
|
||||
if (movelen < FRACUNIT)
|
||||
{
|
||||
|
@ -2265,6 +2293,13 @@ bool P_BounceWall (AActor *mo)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool P_BounceWall (AActor *mo)
|
||||
{
|
||||
FSlide slide;
|
||||
return slide.BounceWall(mo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -2272,26 +2307,23 @@ bool P_BounceWall (AActor *mo)
|
|||
//
|
||||
//============================================================================
|
||||
AActor* linetarget; // who got hit (or NULL)
|
||||
AActor* shootthing;
|
||||
fixed_t shootz; // Height if not aiming up or down
|
||||
fixed_t attackrange;
|
||||
fixed_t aimpitch;
|
||||
|
||||
struct aim_t
|
||||
{
|
||||
|
||||
fixed_t aimpitch;
|
||||
fixed_t attackrange;
|
||||
fixed_t shootz; // Height if not aiming up or down
|
||||
AActor* shootthing;
|
||||
|
||||
fixed_t toppitch, bottompitch;
|
||||
AActor * thing_friend, * thing_other;
|
||||
angle_t pitch_friend, pitch_other;
|
||||
bool notsmart;
|
||||
|
||||
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
|
||||
|
||||
};
|
||||
|
||||
aim_t aim;
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// PTR_AimTraverse
|
||||
|
@ -2299,11 +2331,13 @@ aim_t aim;
|
|||
//
|
||||
//============================================================================
|
||||
|
||||
bool PTR_AimTraverse (intercept_t* in)
|
||||
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
|
||||
{
|
||||
fixed_t & toppitch=aim.toppitch;
|
||||
fixed_t & bottompitch=aim.bottompitch;
|
||||
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
line_t* li;
|
||||
AActor* th;
|
||||
fixed_t pitch;
|
||||
|
@ -2317,16 +2351,16 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
li = in->d.line;
|
||||
|
||||
if ( !(li->flags & ML_TWOSIDED) || (li->flags & ML_BLOCKEVERYTHING) )
|
||||
return false; // stop
|
||||
return; // stop
|
||||
|
||||
// Crosses a two sided line.
|
||||
// A two sided line will restrict the possible target ranges.
|
||||
FLineOpening open;
|
||||
P_LineOpening (open, NULL, li, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
P_LineOpening (open, NULL, li, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
|
||||
if (open.bottom >= open.top)
|
||||
return false; // stop
|
||||
return; // stop
|
||||
|
||||
dist = FixedMul (attackrange, in->frac);
|
||||
|
||||
|
@ -2339,18 +2373,18 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
toppitch = pitch;
|
||||
|
||||
if (toppitch >= bottompitch)
|
||||
return false; // stop
|
||||
return; // stop
|
||||
|
||||
return true; // shot continues
|
||||
continue; // shot continues
|
||||
}
|
||||
|
||||
// shoot a thing
|
||||
th = in->d.thing;
|
||||
if (th == shootthing)
|
||||
return true; // can't shoot self
|
||||
continue; // can't shoot self
|
||||
|
||||
if (!(th->flags&MF_SHOOTABLE))
|
||||
return true; // corpse or something
|
||||
continue; // corpse or something
|
||||
|
||||
// check for physical attacks on a ghost
|
||||
if ((th->flags3 & MF3_GHOST) &&
|
||||
|
@ -2358,7 +2392,7 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
shootthing->player->ReadyWeapon &&
|
||||
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
|
||||
{
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = FixedMul (attackrange, in->frac);
|
||||
|
@ -2367,12 +2401,12 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
thingtoppitch = -(int)R_PointToAngle2 (0, shootz, dist, th->z + th->height);
|
||||
|
||||
if (thingtoppitch > bottompitch)
|
||||
return true; // shot over the thing
|
||||
continue; // shot over the thing
|
||||
|
||||
thingbottompitch = -(int)R_PointToAngle2 (0, shootz, dist, th->z);
|
||||
|
||||
if (thingbottompitch < toppitch)
|
||||
return true; // shot under the thing
|
||||
continue; // shot under the thing
|
||||
|
||||
// this thing can be hit!
|
||||
if (thingtoppitch < toppitch)
|
||||
|
@ -2383,7 +2417,7 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
|
||||
thingpitch = thingtoppitch/2 + thingbottompitch/2;
|
||||
|
||||
if (sv_smartaim && !aim.notsmart)
|
||||
if (sv_smartaim && !notsmart)
|
||||
{
|
||||
// try to be a little smarter about what to aim at!
|
||||
// In particular avoid autoaiming at friends amd barrels.
|
||||
|
@ -2392,8 +2426,8 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
if (sv_smartaim < 2)
|
||||
{
|
||||
// friends don't aim at friends (except players), at least not first
|
||||
aim.thing_friend=th;
|
||||
aim.pitch_friend=thingpitch;
|
||||
thing_friend=th;
|
||||
pitch_friend=thingpitch;
|
||||
}
|
||||
}
|
||||
else if (!(th->flags3&MF3_ISMONSTER) )
|
||||
|
@ -2401,24 +2435,24 @@ bool PTR_AimTraverse (intercept_t* in)
|
|||
if (sv_smartaim < 3)
|
||||
{
|
||||
// don't autoaim at barrels and other shootable stuff unless no monsters have been found
|
||||
aim.thing_other=th;
|
||||
aim.pitch_other=thingpitch;
|
||||
thing_other=th;
|
||||
pitch_other=thingpitch;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linetarget=th;
|
||||
aimpitch=thingpitch;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
linetarget=th;
|
||||
aimpitch=thingpitch;
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
@ -2430,20 +2464,21 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, fixed_t vr
|
|||
{
|
||||
fixed_t x2;
|
||||
fixed_t y2;
|
||||
aim_t aim;
|
||||
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
shootthing = t1;
|
||||
aim.shootthing = t1;
|
||||
|
||||
x2 = t1->x + (distance>>FRACBITS)*finecosine[angle];
|
||||
y2 = t1->y + (distance>>FRACBITS)*finesine[angle];
|
||||
shootz = t1->z + (t1->height>>1) - t1->floorclip;
|
||||
aim.shootz = t1->z + (t1->height>>1) - t1->floorclip;
|
||||
if (t1->player != NULL)
|
||||
{
|
||||
shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor);
|
||||
aim.shootz += FixedMul (t1->player->mo->AttackZOffset, t1->player->crouchfactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
shootz += 8*FRACUNIT;
|
||||
aim.shootz += 8*FRACUNIT;
|
||||
}
|
||||
|
||||
// can't shoot outside view angles
|
||||
|
@ -2466,30 +2501,30 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, fixed_t vr
|
|||
aim.bottompitch = t1->pitch + vrange;
|
||||
aim.notsmart = forcenosmart;
|
||||
|
||||
attackrange = distance;
|
||||
aim.attackrange = distance;
|
||||
linetarget = NULL;
|
||||
|
||||
// for smart aiming
|
||||
aim.thing_friend=aim.thing_other=NULL;
|
||||
|
||||
// Information for tracking crossed 3D floors
|
||||
aimpitch=t1->pitch;
|
||||
P_PathTraverse (t1->x, t1->y, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_AimTraverse);
|
||||
aim.aimpitch=t1->pitch;
|
||||
aim.AimTraverse (t1->x, t1->y, x2, y2);
|
||||
|
||||
if (!linetarget)
|
||||
{
|
||||
if (aim.thing_other)
|
||||
{
|
||||
linetarget=aim.thing_other;
|
||||
aimpitch=aim.pitch_other;
|
||||
aim.aimpitch=aim.pitch_other;
|
||||
}
|
||||
else if (aim.thing_friend)
|
||||
{
|
||||
linetarget=aim.thing_friend;
|
||||
aimpitch=aim.pitch_friend;
|
||||
aim.aimpitch=aim.pitch_friend;
|
||||
}
|
||||
}
|
||||
return linetarget ? aimpitch : t1->pitch;
|
||||
return linetarget ? aim.aimpitch : t1->pitch;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2565,8 +2600,6 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
{
|
||||
shootz += 8*FRACUNIT;
|
||||
}
|
||||
attackrange = distance;
|
||||
aimpitch = pitch;
|
||||
|
||||
hitGhosts = (t1->player != NULL &&
|
||||
t1->player->ReadyWeapon != NULL &&
|
||||
|
@ -2716,7 +2749,7 @@ AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance,
|
|||
puff = P_SpawnPuff (pufftype, hitx, hity, hitz, angle - ANG180, 2, flags|PF_HITTHING|PF_TEMPORARY);
|
||||
killPuff = true;
|
||||
}
|
||||
SpawnDeepSplash (t1, trace, puff, vx, vy, vz);
|
||||
SpawnDeepSplash (t1, trace, puff, vx, vy, vz, shootz);
|
||||
}
|
||||
}
|
||||
if (killPuff && puff != NULL)
|
||||
|
@ -2903,6 +2936,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
fixed_t x1, y1;
|
||||
FVector3 start, end;
|
||||
FTraceResults trace;
|
||||
fixed_t shootz;
|
||||
|
||||
pitch = (angle_t)(-source->pitch) >> ANGLETOFINESHIFT;
|
||||
angle = source->angle >> ANGLETOFINESHIFT;
|
||||
|
@ -2981,7 +3015,7 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
AActor *thepuff = Spawn ("BulletPuff", 0, 0, 0, ALLOW_REPLACE);
|
||||
if (thepuff != NULL)
|
||||
{
|
||||
SpawnDeepSplash (source, trace, thepuff, vx, vy, vz);
|
||||
SpawnDeepSplash (source, trace, thepuff, vx, vy, vz, shootz);
|
||||
thepuff->Destroy ();
|
||||
}
|
||||
}
|
||||
|
@ -3024,10 +3058,8 @@ void P_RailAttack (AActor *source, int damage, int offset, int color1, int color
|
|||
//
|
||||
CVAR (Float, chase_height, -8.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
CVAR (Float, chase_dist, 90.f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
|
||||
fixed_t CameraX, CameraY, CameraZ;
|
||||
sector_t *CameraSector;
|
||||
|
||||
void P_AimCamera (AActor *t1)
|
||||
void P_AimCamera (AActor *t1, fixed_t &CameraX, fixed_t &CameraY, fixed_t &CameraZ, sector_t *&CameraSector)
|
||||
{
|
||||
fixed_t distance = (fixed_t)(chase_dist * FRACUNIT);
|
||||
angle_t angle = (t1->angle - ANG180) >> ANGLETOFINESHIFT;
|
||||
|
@ -3064,44 +3096,47 @@ void P_AimCamera (AActor *t1)
|
|||
//
|
||||
// USE LINES
|
||||
//
|
||||
AActor *usething;
|
||||
bool foundline;
|
||||
|
||||
bool PTR_UseTraverse (intercept_t *in)
|
||||
bool P_UseTraverse(AActor *usething, fixed_t endx, fixed_t endy, bool &foundline)
|
||||
{
|
||||
FPathTraverse it(usething->x, usething->y, endx, endy, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
// [RH] Check for things to talk with or use a puzzle item on
|
||||
if (!in->isaline)
|
||||
{
|
||||
if (usething==in->d.thing) return true;
|
||||
if (usething==in->d.thing) continue;
|
||||
// Check thing
|
||||
|
||||
// Check for puzzle item use or USESPECIAL flag
|
||||
if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == USE_PUZZLE_ITEM_SPECIAL)
|
||||
if (in->d.thing->flags5 & MF5_USESPECIAL || in->d.thing->special == UsePuzzleItem)
|
||||
{
|
||||
if (LineSpecials[in->d.thing->special] (NULL, usething, false,
|
||||
in->d.thing->args[0], in->d.thing->args[1], in->d.thing->args[2],
|
||||
in->d.thing->args[3], in->d.thing->args[4]))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// Dead things can't talk.
|
||||
if (in->d.thing->health <= 0)
|
||||
{
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
// Fighting things don't talk either.
|
||||
if (in->d.thing->flags4 & MF4_INCOMBAT)
|
||||
{
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
if (in->d.thing->Conversation != NULL)
|
||||
{
|
||||
// Give the NPC a chance to play a brief animation
|
||||
in->d.thing->ConversationAnimation (0);
|
||||
P_StartConversation (in->d.thing, usething, true, true);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
FLineOpening open;
|
||||
// [RH] The range passed to P_PathTraverse was doubled so that it could
|
||||
|
@ -3110,23 +3145,23 @@ bool PTR_UseTraverse (intercept_t *in)
|
|||
if (in->frac > FRACUNIT/2)
|
||||
{
|
||||
// don't pass usething here. It will not do what might be expected!
|
||||
P_LineOpening (open, NULL, in->d.line, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
return open.range>0;
|
||||
P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
if (open.range <= 0) return false;
|
||||
else continue;
|
||||
}
|
||||
|
||||
if (in->d.line->special == 0 || (GET_SPAC(in->d.line->flags) != SPAC_USETHROUGH &&
|
||||
GET_SPAC(in->d.line->flags) != SPAC_USE))
|
||||
{
|
||||
blocked:
|
||||
blocked:
|
||||
if (in->d.line->flags & ML_BLOCKEVERYTHING)
|
||||
{
|
||||
open.range = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
P_LineOpening (open, NULL, in->d.line, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
}
|
||||
if (open.range <= 0 ||
|
||||
(in->d.line->special != 0 && (i_compatflags & COMPATF_USEBLOCKING)))
|
||||
|
@ -3139,7 +3174,7 @@ blocked:
|
|||
|
||||
if (sec->SecActTarget && sec->SecActTarget->TriggerAction (usething, SECSPAC_Use))
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
sec = P_PointOnLineSide(usething->x, usething->y, in->d.line) == 0?
|
||||
|
@ -3148,17 +3183,17 @@ blocked:
|
|||
if (sec != NULL && sec->SecActTarget &&
|
||||
sec->SecActTarget->TriggerAction (usething, SECSPAC_UseWall))
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (usething->player)
|
||||
{
|
||||
S_Sound (usething, CHAN_VOICE, "*usefail", 1, ATTN_IDLE);
|
||||
}
|
||||
return false; // can't use through a wall
|
||||
return true; // can't use through a wall
|
||||
}
|
||||
foundline = true;
|
||||
return true; // not a special line, but keep checking
|
||||
continue; // not a special line, but keep checking
|
||||
}
|
||||
|
||||
if (P_PointOnLineSide (usething->x, usething->y, in->d.line) == 1)
|
||||
|
@ -3175,12 +3210,16 @@ blocked:
|
|||
// it through, including SPAC_USETHROUGH.
|
||||
if (i_compatflags & COMPATF_USEBLOCKING)
|
||||
{
|
||||
return GET_SPAC(in->d.line->flags) == SPAC_USETHROUGH;
|
||||
if (GET_SPAC(in->d.line->flags) == SPAC_USETHROUGH) continue;
|
||||
else return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GET_SPAC(in->d.line->flags) != SPAC_USE;
|
||||
if (GET_SPAC(in->d.line->flags) != SPAC_USE) continue;
|
||||
else return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns false if a "oof" sound should be made because of a blocking
|
||||
|
@ -3193,19 +3232,27 @@ blocked:
|
|||
// by Lee Killough
|
||||
//
|
||||
|
||||
bool PTR_NoWayTraverse (intercept_t *in)
|
||||
bool P_NoWayTraverse (AActor *usething, fixed_t endx, fixed_t endy)
|
||||
{
|
||||
FPathTraverse it(usething->x, usething->y, endx, endy, PT_ADDLINES);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
line_t *ld = in->d.line;
|
||||
FLineOpening open;
|
||||
|
||||
// [GrafZahl] de-obfuscated. Was I the only one who was unable to makes sense out of
|
||||
// this convoluted mess?
|
||||
if (ld->special) return true;
|
||||
if (ld->flags&(ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)) return false;
|
||||
P_LineOpening(open, NULL, ld, trace.x+FixedMul(trace.dx, in->frac),trace.y+FixedMul(trace.dy, in->frac));
|
||||
return open.range >0 &&
|
||||
open.bottom <= usething->z + usething->MaxStepHeight &&
|
||||
open.top >= usething->z + usething->height;
|
||||
if (ld->special) continue;
|
||||
if (ld->flags&(ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)) return true;
|
||||
P_LineOpening(open, NULL, ld, it.Trace().x+FixedMul(it.Trace().dx, in->frac),
|
||||
it.Trace().y+FixedMul(it.Trace().dy, in->frac));
|
||||
if (open.range <= 0 ||
|
||||
open.bottom > usething->z + usething->MaxStepHeight ||
|
||||
open.top < usething->z + usething->height) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3220,16 +3267,14 @@ bool PTR_NoWayTraverse (intercept_t *in)
|
|||
void P_UseLines (player_t *player)
|
||||
{
|
||||
angle_t angle;
|
||||
fixed_t x1, y1, x2, y2;
|
||||
fixed_t x2, y2;
|
||||
bool foundline;
|
||||
|
||||
usething = player->mo;
|
||||
foundline = false;
|
||||
|
||||
angle = player->mo->angle >> ANGLETOFINESHIFT;
|
||||
x1 = player->mo->x;
|
||||
y1 = player->mo->y;
|
||||
x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]*2;
|
||||
y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]*2;
|
||||
x2 = player->mo->x + (USERANGE>>FRACBITS)*finecosine[angle]*2;
|
||||
y2 = player->mo->y + (USERANGE>>FRACBITS)*finesine[angle]*2;
|
||||
|
||||
// old code:
|
||||
//
|
||||
|
@ -3237,80 +3282,19 @@ void P_UseLines (player_t *player)
|
|||
//
|
||||
// This added test makes the "oof" sound work on 2s lines -- killough:
|
||||
|
||||
if (P_PathTraverse (x1, y1, x2, y2, PT_ADDLINES|PT_ADDTHINGS, PTR_UseTraverse))
|
||||
if (!P_UseTraverse (player->mo, x2, y2, foundline))
|
||||
{ // [RH] Give sector a chance to eat the use
|
||||
sector_t *sec = usething->Sector;
|
||||
sector_t *sec = player->mo->Sector;
|
||||
int spac = SECSPAC_Use;
|
||||
if (foundline)
|
||||
spac |= SECSPAC_UseWall;
|
||||
if ((!sec->SecActTarget ||
|
||||
!sec->SecActTarget->TriggerAction (usething, spac)) &&
|
||||
!P_PathTraverse (x1, y1, x2, y2, PT_ADDLINES, PTR_NoWayTraverse))
|
||||
if (foundline) spac |= SECSPAC_UseWall;
|
||||
if ((!sec->SecActTarget || !sec->SecActTarget->TriggerAction (player->mo, spac)) &&
|
||||
P_NoWayTraverse (player->mo, x2, y2))
|
||||
{
|
||||
S_Sound (usething, CHAN_VOICE, "*usefail", 1, ATTN_IDLE);
|
||||
S_Sound (player->mo, CHAN_VOICE, "*usefail", 1, ATTN_IDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PTR_PuzzleItemTraverse
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static AActor *PuzzleItemUser;
|
||||
static int PuzzleItemType;
|
||||
static bool PuzzleActivated;
|
||||
|
||||
bool PTR_PuzzleItemTraverse (intercept_t *in)
|
||||
{
|
||||
AActor *mobj;
|
||||
FLineOpening open;
|
||||
|
||||
if (in->isaline)
|
||||
{ // Check line
|
||||
if (in->d.line->special != USE_PUZZLE_ITEM_SPECIAL)
|
||||
{
|
||||
P_LineOpening (open, NULL, in->d.line, trace.x + FixedMul (trace.dx, in->frac),
|
||||
trace.y + FixedMul (trace.dy, in->frac));
|
||||
if (open.range <= 0)
|
||||
{
|
||||
return false; // can't use through a wall
|
||||
}
|
||||
return true; // Continue searching
|
||||
}
|
||||
if (P_PointOnLineSide (PuzzleItemUser->x, PuzzleItemUser->y,
|
||||
in->d.line) == 1)
|
||||
{ // Don't use back sides
|
||||
return false;
|
||||
}
|
||||
if (PuzzleItemType != in->d.line->args[0])
|
||||
{ // Item type doesn't match
|
||||
return false;
|
||||
}
|
||||
P_StartScript (PuzzleItemUser, in->d.line, in->d.line->args[1], NULL, 0,
|
||||
in->d.line->args[2], in->d.line->args[3], in->d.line->args[4], true, false);
|
||||
in->d.line->special = 0;
|
||||
PuzzleActivated = true;
|
||||
return false; // Stop searching
|
||||
}
|
||||
// Check thing
|
||||
mobj = in->d.thing;
|
||||
if (mobj->special != USE_PUZZLE_ITEM_SPECIAL)
|
||||
{ // Wrong special
|
||||
return true;
|
||||
}
|
||||
if (PuzzleItemType != mobj->args[0])
|
||||
{ // Item type doesn't match
|
||||
return true;
|
||||
}
|
||||
P_StartScript (PuzzleItemUser, NULL, mobj->args[1], NULL, 0,
|
||||
mobj->args[2], mobj->args[3], mobj->args[4], true, false);
|
||||
mobj->special = 0;
|
||||
PuzzleActivated = true;
|
||||
return false; // Stop searching
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_UsePuzzleItem
|
||||
|
@ -3319,36 +3303,72 @@ bool PTR_PuzzleItemTraverse (intercept_t *in)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool P_UsePuzzleItem (AActor *actor, int itemType)
|
||||
bool P_UsePuzzleItem (AActor *PuzzleItemUser, int PuzzleItemType)
|
||||
{
|
||||
int angle;
|
||||
fixed_t x1, y1, x2, y2;
|
||||
|
||||
PuzzleItemType = itemType;
|
||||
PuzzleItemUser = actor;
|
||||
PuzzleActivated = false;
|
||||
angle = actor->angle>>ANGLETOFINESHIFT;
|
||||
x1 = actor->x;
|
||||
y1 = actor->y;
|
||||
angle = PuzzleItemUser->angle>>ANGLETOFINESHIFT;
|
||||
x1 = PuzzleItemUser->x;
|
||||
y1 = PuzzleItemUser->y;
|
||||
x2 = x1+(USERANGE>>FRACBITS)*finecosine[angle];
|
||||
y2 = y1+(USERANGE>>FRACBITS)*finesine[angle];
|
||||
P_PathTraverse (x1, y1, x2, y2, PT_ADDLINES|PT_ADDTHINGS,
|
||||
PTR_PuzzleItemTraverse);
|
||||
return PuzzleActivated;
|
||||
|
||||
FPathTraverse it(x1, y1, x2, y2, PT_ADDLINES|PT_ADDTHINGS);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
AActor *mobj;
|
||||
FLineOpening open;
|
||||
|
||||
if (in->isaline)
|
||||
{ // Check line
|
||||
if (in->d.line->special != UsePuzzleItem)
|
||||
{
|
||||
P_LineOpening (open, NULL, in->d.line, it.Trace().x + FixedMul (it.Trace().dx, in->frac),
|
||||
it.Trace().y + FixedMul (it.Trace().dy, in->frac));
|
||||
if (open.range <= 0)
|
||||
{
|
||||
return false; // can't use through a wall
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (P_PointOnLineSide (PuzzleItemUser->x, PuzzleItemUser->y, in->d.line) == 1)
|
||||
{ // Don't use back sides
|
||||
return false;
|
||||
}
|
||||
if (PuzzleItemType != in->d.line->args[0])
|
||||
{ // Item type doesn't match
|
||||
return false;
|
||||
}
|
||||
P_StartScript (PuzzleItemUser, in->d.line, in->d.line->args[1], NULL, 0,
|
||||
in->d.line->args[2], in->d.line->args[3], in->d.line->args[4], true, false);
|
||||
in->d.line->special = 0;
|
||||
return true;
|
||||
}
|
||||
// Check thing
|
||||
mobj = in->d.thing;
|
||||
if (mobj->special != UsePuzzleItem)
|
||||
{ // Wrong special
|
||||
continue;
|
||||
}
|
||||
if (PuzzleItemType != mobj->args[0])
|
||||
{ // Item type doesn't match
|
||||
continue;
|
||||
}
|
||||
P_StartScript (PuzzleItemUser, NULL, mobj->args[1], NULL, 0,
|
||||
mobj->args[2], mobj->args[3], mobj->args[4], true, false);
|
||||
mobj->special = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
// RADIUS ATTACK
|
||||
//
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
// PIT_RadiusAttack
|
||||
//
|
||||
// "bombsource" is the creature that caused the explosion at "bombspot".
|
||||
// [RH] Now it knows about vertical distances and can thrust things vertically.
|
||||
//=============================================================================
|
||||
|
||||
// [RH] Damage scale to apply to thing that shot the missile.
|
||||
static float selfthrustscale;
|
||||
|
||||
|
@ -4428,7 +4448,7 @@ void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
|
|||
}
|
||||
|
||||
static void SpawnDeepSplash (AActor *t1, const FTraceResults &trace, AActor *puff,
|
||||
fixed_t vx, fixed_t vy, fixed_t vz)
|
||||
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t shootz)
|
||||
{
|
||||
fixed_t num, den, hitdist;
|
||||
const secplane_t *plane = &trace.CrossedWater->heightsec->floorplane;
|
||||
|
|
271
src/p_maputl.cpp
271
src/p_maputl.cpp
|
@ -59,57 +59,6 @@ fixed_t P_AproxDistance (fixed_t dx, fixed_t dy)
|
|||
return (dx < dy) ? dx+dy-(dx>>1) : dx+dy-(dy>>1);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_BoxOnLineSide
|
||||
//
|
||||
// Considers the line to be infinite
|
||||
// Returns side 0 or 1, -1 if box crosses the line.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int P_BoxOnLineSide (const fixed_t *tmbox, const line_t *ld)
|
||||
{
|
||||
int p1;
|
||||
int p2;
|
||||
|
||||
switch (ld->slopetype)
|
||||
{
|
||||
case ST_HORIZONTAL:
|
||||
p1 = tmbox[BOXTOP] > ld->v1->y;
|
||||
p2 = tmbox[BOXBOTTOM] > ld->v1->y;
|
||||
if (ld->dx < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_VERTICAL:
|
||||
p1 = tmbox[BOXRIGHT] < ld->v1->x;
|
||||
p2 = tmbox[BOXLEFT] < ld->v1->x;
|
||||
if (ld->dy < 0)
|
||||
{
|
||||
p1 ^= 1;
|
||||
p2 ^= 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case ST_POSITIVE:
|
||||
p1 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
|
||||
case ST_NEGATIVE:
|
||||
default: // Just to assure GCC that p1 and p2 really do get initialized
|
||||
p1 = P_PointOnLineSide (tmbox[BOXRIGHT], tmbox[BOXTOP], ld);
|
||||
p2 = P_PointOnLineSide (tmbox[BOXLEFT], tmbox[BOXBOTTOM], ld);
|
||||
break;
|
||||
}
|
||||
|
||||
return (p1 == p2) ? p1 : -1;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_InterceptVector
|
||||
|
@ -264,6 +213,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
// THING POSITION SETTING
|
||||
//
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_UnsetThingPosition
|
||||
// Unlinks a thing from block map and sectors.
|
||||
|
@ -271,6 +221,8 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
|||
// lookups maintaining lists of things inside
|
||||
// these structures need to be updated.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AActor::UnlinkFromWorld ()
|
||||
{
|
||||
sector_list = NULL;
|
||||
|
@ -326,11 +278,14 @@ void AActor::UnlinkFromWorld ()
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_SetThingPosition
|
||||
// Links a thing into both a block and a subsector based on it's x y.
|
||||
// Sets thing->sector properly
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void AActor::LinkToWorld (bool buggy)
|
||||
{
|
||||
// link into subsector
|
||||
|
@ -433,12 +388,15 @@ void AActor::LinkToWorld (sector_t *sec)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// [RH] LinkToWorldForMapThing
|
||||
//
|
||||
// Emulate buggy PointOnLineSide and fix actors that lie on
|
||||
// lines to compensate for some IWAD maps.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node)
|
||||
{
|
||||
// [RH] This might have been faster than two multiplies and an
|
||||
|
@ -542,7 +500,6 @@ sector_t *AActor::LinkToWorldForMapThing ()
|
|||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
// Not inside the line's bounding box
|
||||
if (x + radius <= ldef->bbox[BOXLEFT]
|
||||
|| x - radius >= ldef->bbox[BOXRIGHT]
|
||||
|
@ -586,39 +543,6 @@ sector_t *AActor::LinkToWorldForMapThing ()
|
|||
y += FixedMul(distance, finesine[finean]);
|
||||
return P_PointInSector (x, y);
|
||||
}
|
||||
#else
|
||||
if (DMulScale32 (y - ldef->v1->y, ldef->dx, ldef->v1->x - x, ldef->dy) == 0)
|
||||
{
|
||||
// It touches the infinite line; now make sure it touches the linedef
|
||||
SQWORD num, den;
|
||||
|
||||
den = (SQWORD)ldef->dx*ldef->dx + (SQWORD)ldef->dy*ldef->dy;
|
||||
if (den != 0)
|
||||
{
|
||||
num = (SQWORD)(x-ldef->v1->x)*ldef->dx+(SQWORD)(y-ldef->v1->y)*ldef->dy;
|
||||
if (num >= 0 && num <= den)
|
||||
{
|
||||
DPrintf ("%s at (%d,%d) lies directly on %s line %d\n",
|
||||
this->GetClass()->TypeName.GetChars(), x>>FRACBITS, y>>FRACBITS,
|
||||
ldef->dx == 0? "vertical" : ldef->dy == 0? "horizontal" : "diagonal",
|
||||
ldef-lines);
|
||||
angle_t finean = R_PointToAngle2 (0, 0, ldef->dx, ldef->dy);
|
||||
if (ldef->backsector != NULL && ldef->backsector == ssec->sector)
|
||||
{
|
||||
finean += ANGLE_90;
|
||||
}
|
||||
else
|
||||
{
|
||||
finean -= ANGLE_90;
|
||||
}
|
||||
finean >>= ANGLETOFINESHIFT;
|
||||
x += finecosine[finean]) >> 2;
|
||||
y += finesine[finean]) >> 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -808,34 +732,20 @@ line_t *FBlockLinesIterator::Next()
|
|||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: GetCheckArray
|
||||
// FBlockThingsIterator :: CheckArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
TDeletingArray< FBlockThingsIterator::BTChecked* > FBlockThingsIterator::FreeBTChecked;
|
||||
TArray<AActor *> FBlockThingsIterator::CheckArray(32);
|
||||
|
||||
FBlockThingsIterator::BTChecked *FBlockThingsIterator::GetCheckArray()
|
||||
int FBlockThingsIterator::GetCheckIndex()
|
||||
{
|
||||
dontfreecheck = false;
|
||||
if (FreeBTChecked.Size() != 0)
|
||||
{
|
||||
BTChecked *ret;
|
||||
FreeBTChecked.Pop(ret);
|
||||
ret->Clear();
|
||||
return ret;
|
||||
}
|
||||
return new BTChecked();
|
||||
return CheckArray.Size();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: FreeCheckArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FBlockThingsIterator::FreeCheckArray()
|
||||
void FBlockThingsIterator::SetCheckIndex(int newvalue)
|
||||
{
|
||||
FreeBTChecked.Push(checkarray);
|
||||
CheckArray.Resize(newvalue);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -844,17 +754,19 @@ void FBlockThingsIterator::FreeCheckArray()
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int _maxy, TArray<AActor *> *Check)
|
||||
FBlockThingsIterator::FBlockThingsIterator(int x, int y, int check)
|
||||
{
|
||||
if (Check != NULL)
|
||||
{
|
||||
checkarray = Check;
|
||||
checkindex = check;
|
||||
dontfreecheck = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
checkarray = GetCheckArray();
|
||||
}
|
||||
minx = maxx = x;
|
||||
miny = maxy = y;
|
||||
Reset();
|
||||
}
|
||||
|
||||
FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int _maxy)
|
||||
{
|
||||
checkindex = CheckArray.Size();
|
||||
dontfreecheck = false;
|
||||
minx = _minx;
|
||||
maxx = _maxx;
|
||||
miny = _miny;
|
||||
|
@ -864,7 +776,8 @@ FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int
|
|||
|
||||
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
||||
{
|
||||
checkarray = GetCheckArray();
|
||||
checkindex = CheckArray.Size();
|
||||
dontfreecheck = false;
|
||||
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||
|
@ -872,6 +785,17 @@ FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
|||
Reset();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: FreeCheckArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FBlockThingsIterator::~FBlockThingsIterator()
|
||||
{
|
||||
if (!dontfreecheck) CheckArray.Resize(checkindex);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: StartBlock
|
||||
|
@ -910,16 +834,16 @@ AActor *FBlockThingsIterator::Next()
|
|||
|
||||
block = block->NextActor;
|
||||
// Don't recheck things that were already checked
|
||||
for (i = (int)checkarray->Size() - 1; i >= 0; --i)
|
||||
for (i = (int)CheckArray.Size() - 1; i >= checkindex; --i)
|
||||
{
|
||||
if ((*checkarray)[i] == me)
|
||||
if (CheckArray[i] == me)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
if (i < checkindex)
|
||||
{
|
||||
checkarray->Push (me);
|
||||
CheckArray.Push (me);
|
||||
return me;
|
||||
}
|
||||
}
|
||||
|
@ -967,16 +891,18 @@ AActor *FRadiusThingsIterator::Next()
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// INTERCEPT ROUTINES
|
||||
// FPathTraverse :: Intercepts
|
||||
//
|
||||
TArray<intercept_t> intercepts (128);
|
||||
//===========================================================================
|
||||
|
||||
divline_t trace;
|
||||
int ptflags;
|
||||
TArray<intercept_t> FPathTraverse::intercepts(128);
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// PIT_AddLineIntercepts.
|
||||
// FPathTraverse :: AddLineIntercepts.
|
||||
// Looks for lines in the given block
|
||||
// that intercept the given trace
|
||||
// to add to the intercepts list.
|
||||
|
@ -984,7 +910,9 @@ int ptflags;
|
|||
// A line is crossed if its endpoints
|
||||
// are on opposite sides of the trace.
|
||||
//
|
||||
void P_AddLineIntercepts(int bx, int by)
|
||||
//===========================================================================
|
||||
|
||||
void FPathTraverse::AddLineIntercepts(int bx, int by)
|
||||
{
|
||||
FBlockLinesIterator it(bx, by, bx, by, true);
|
||||
line_t *ld;
|
||||
|
@ -1023,18 +951,22 @@ void P_AddLineIntercepts(int bx, int by)
|
|||
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = true;
|
||||
newintercept.done = false;
|
||||
newintercept.d.line = ld;
|
||||
intercepts.Push (newintercept);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// PIT_AddThingIntercepts
|
||||
// FPathTraverse :: AddThingIntercepts
|
||||
//
|
||||
void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
||||
//===========================================================================
|
||||
|
||||
void FPathTraverse::AddThingIntercepts (int bx, int by, int checkindex)
|
||||
{
|
||||
FBlockThingsIterator it(bx, by, bx, by, &checkbt);
|
||||
FBlockThingsIterator it(bx, by, checkindex);
|
||||
AActor *thing;
|
||||
|
||||
while ((thing = it.Next()))
|
||||
|
@ -1099,6 +1031,7 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
|||
intercept_t newintercept;
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = false;
|
||||
newintercept.done = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
continue;
|
||||
|
@ -1113,6 +1046,7 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
|||
intercept_t newintercept;
|
||||
newintercept.frac = 0;
|
||||
newintercept.isaline = false;
|
||||
newintercept.done = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
}
|
||||
|
@ -1120,60 +1054,41 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_TraverseIntercepts
|
||||
// Returns true if the traverser function returns true
|
||||
// for all lines.
|
||||
// FPathTraverse :: Next
|
||||
//
|
||||
bool P_TraverseIntercepts (traverser_t func, fixed_t maxfrac)
|
||||
//===========================================================================
|
||||
|
||||
intercept_t *FPathTraverse::Next()
|
||||
{
|
||||
unsigned int count;
|
||||
fixed_t dist;
|
||||
unsigned int scanpos;
|
||||
intercept_t *scan;
|
||||
intercept_t *in = NULL;
|
||||
|
||||
count = intercepts.Size ();
|
||||
|
||||
while (count--)
|
||||
fixed_t dist = FIXED_MAX;
|
||||
for (unsigned scanpos = intercept_index; scanpos < intercepts.Size (); scanpos++)
|
||||
{
|
||||
dist = FIXED_MAX;
|
||||
for (scanpos = 0; scanpos < intercepts.Size (); scanpos++)
|
||||
{
|
||||
scan = &intercepts[scanpos];
|
||||
if (scan->frac < dist)
|
||||
intercept_t *scan = &intercepts[scanpos];
|
||||
if (scan->frac < dist && !scan->done)
|
||||
{
|
||||
dist = scan->frac;
|
||||
in = scan;
|
||||
}
|
||||
}
|
||||
|
||||
if (dist > maxfrac || in == NULL)
|
||||
return true; // checked everything in range
|
||||
|
||||
if (!func (in))
|
||||
return false; // don't bother going farther
|
||||
|
||||
in->frac = FIXED_MAX;
|
||||
}
|
||||
|
||||
return true; // everything was traversed
|
||||
if (dist > maxfrac || in == NULL) return NULL; // checked everything in range
|
||||
in->done = true;
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_PathTraverse
|
||||
// FPathTraverse
|
||||
// Traces a line from x1,y1 to x2,y2,
|
||||
// calling the traverser function for each.
|
||||
// Returns true if the traverser function returns true
|
||||
// for all lines.
|
||||
//
|
||||
bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, bool (*trav) (intercept_t *))
|
||||
{
|
||||
static TArray<AActor *> pathbt;
|
||||
//===========================================================================
|
||||
|
||||
FPathTraverse::FPathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags)
|
||||
{
|
||||
fixed_t xt1;
|
||||
fixed_t yt1;
|
||||
fixed_t xt2;
|
||||
|
@ -1196,8 +1111,7 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
int count;
|
||||
|
||||
validcount++;
|
||||
intercepts.Clear ();
|
||||
pathbt.Clear ();
|
||||
intercept_index = intercepts.Size();
|
||||
|
||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||
x1 += FRACUNIT; // don't side exactly on a line
|
||||
|
@ -1288,16 +1202,18 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
mapx = xt1;
|
||||
mapy = yt1;
|
||||
|
||||
// we want to use one list of checked actors for the entire operation
|
||||
int BTI_CheckIndex = FBlockThingsIterator::GetCheckIndex();
|
||||
for (count = 0 ; count < 100 ; count++)
|
||||
{
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
P_AddLineIntercepts(mapx, mapy);
|
||||
AddLineIntercepts(mapx, mapy);
|
||||
}
|
||||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
P_AddThingIntercepts(mapx, mapy, pathbt);
|
||||
AddThingIntercepts(mapx, mapy, BTI_CheckIndex);
|
||||
}
|
||||
|
||||
if (mapx == xt2 && mapy == yt2)
|
||||
|
@ -1329,14 +1245,14 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
// be checked.
|
||||
if (flags & PT_ADDLINES)
|
||||
{
|
||||
P_AddLineIntercepts(mapx + mapxstep, mapy);
|
||||
P_AddLineIntercepts(mapx, mapy + mapystep);
|
||||
AddLineIntercepts(mapx + mapxstep, mapy);
|
||||
AddLineIntercepts(mapx, mapy + mapystep);
|
||||
}
|
||||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
P_AddThingIntercepts(mapx + mapxstep, mapy, pathbt);
|
||||
P_AddThingIntercepts(mapx, mapy + mapystep, pathbt);
|
||||
AddThingIntercepts(mapx + mapxstep, mapy, BTI_CheckIndex);
|
||||
AddThingIntercepts(mapx, mapy + mapystep, BTI_CheckIndex);
|
||||
}
|
||||
xintercept += xstep;
|
||||
yintercept += ystep;
|
||||
|
@ -1345,10 +1261,16 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
break;
|
||||
}
|
||||
}
|
||||
// go through the sorted list
|
||||
return P_TraverseIntercepts ( trav, FRACUNIT );
|
||||
FBlockThingsIterator::SetCheckIndex(BTI_CheckIndex);
|
||||
maxfrac = FRACUNIT;
|
||||
}
|
||||
|
||||
FPathTraverse::~FPathTraverse()
|
||||
{
|
||||
intercepts.Resize(intercept_index);
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_RoughMonsterSearch
|
||||
|
@ -1473,4 +1395,3 @@ static AActor *RoughBlockCheck (AActor *mo, int index)
|
|||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
|
|||
|
||||
extern cycle_t BotSupportCycles;
|
||||
extern cycle_t BotWTG;
|
||||
extern fixed_t attackrange;
|
||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
||||
EXTERN_CVAR (Int, cl_rockettrails)
|
||||
|
||||
|
|
|
@ -36,6 +36,9 @@ This uses specialized forms of the maputils routines for optimized performance
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
static TArray<intercept_t> intercepts (128);
|
||||
static divline_t trace;
|
||||
|
||||
static fixed_t sightzstart; // eye z of looker
|
||||
static fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||
static int SeePastBlockEverything, SeePastShootableLines;
|
||||
|
|
135
src/p_trace.cpp
135
src/p_trace.cpp
|
@ -36,21 +36,26 @@
|
|||
#include "p_local.h"
|
||||
#include "i_system.h"
|
||||
|
||||
static fixed_t StartZ;
|
||||
static fixed_t Vx, Vy, Vz;
|
||||
static DWORD ActorMask, WallMask;
|
||||
static AActor *IgnoreThis;
|
||||
static FTraceResults *Results;
|
||||
static sector_t *CurSector;
|
||||
static fixed_t MaxDist;
|
||||
static fixed_t EnterDist;
|
||||
static bool (*TraceCallback)(FTraceResults &res);
|
||||
static DWORD TraceFlags;
|
||||
struct FTraceInfo
|
||||
{
|
||||
fixed_t StartX, StartY, StartZ;
|
||||
fixed_t Vx, Vy, Vz;
|
||||
DWORD ActorMask, WallMask;
|
||||
AActor *IgnoreThis;
|
||||
FTraceResults *Results;
|
||||
sector_t *CurSector;
|
||||
fixed_t MaxDist;
|
||||
fixed_t EnterDist;
|
||||
bool (*TraceCallback)(FTraceResults &res);
|
||||
DWORD TraceFlags;
|
||||
|
||||
bool TraceTraverse (int ptflags);
|
||||
bool CheckSectorPlane (const sector_t *sector, bool checkFloor);
|
||||
};
|
||||
|
||||
static bool PTR_TraceIterator (intercept_t *);
|
||||
static bool CheckSectorPlane (const sector_t *sector, bool checkFloor);
|
||||
static bool EditTraceResult (DWORD flags, FTraceResults &res);
|
||||
|
||||
|
||||
bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
|
||||
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t maxDist,
|
||||
DWORD actorMask, DWORD wallMask, AActor *ignore,
|
||||
|
@ -58,42 +63,45 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
|
|||
DWORD flags, bool (*callback)(FTraceResults &res))
|
||||
{
|
||||
int ptflags;
|
||||
FTraceInfo inf;
|
||||
|
||||
ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS : PT_ADDLINES;
|
||||
|
||||
StartZ = z;
|
||||
Vx = vx;
|
||||
Vy = vy;
|
||||
Vz = vz;
|
||||
ActorMask = actorMask;
|
||||
WallMask = wallMask;
|
||||
IgnoreThis = ignore;
|
||||
CurSector = sector;
|
||||
MaxDist = maxDist;
|
||||
EnterDist = 0;
|
||||
TraceCallback = callback;
|
||||
TraceFlags = flags;
|
||||
inf.StartX = x;
|
||||
inf.StartY = y;
|
||||
inf.StartZ = z;
|
||||
inf.Vx = vx;
|
||||
inf.Vy = vy;
|
||||
inf.Vz = vz;
|
||||
inf.ActorMask = actorMask;
|
||||
inf.WallMask = wallMask;
|
||||
inf.IgnoreThis = ignore;
|
||||
inf.CurSector = sector;
|
||||
inf.MaxDist = maxDist;
|
||||
inf.EnterDist = 0;
|
||||
inf.TraceCallback = callback;
|
||||
inf.TraceFlags = flags;
|
||||
res.CrossedWater = NULL;
|
||||
Results = &res;
|
||||
inf.Results = &res;
|
||||
|
||||
res.HitType = TRACE_HitNone;
|
||||
|
||||
if (P_PathTraverse (x, y, x + FixedMul (vx, maxDist), y + FixedMul (vy, maxDist),
|
||||
ptflags, PTR_TraceIterator))
|
||||
{ // check for intersection with floor/ceiling
|
||||
res.Sector = CurSector;
|
||||
|
||||
if (CheckSectorPlane (CurSector, true))
|
||||
if (inf.TraceTraverse (ptflags))
|
||||
{ // check for intersection with floor/ceiling
|
||||
res.Sector = inf.CurSector;
|
||||
|
||||
if (inf.CheckSectorPlane (inf.CurSector, true))
|
||||
{
|
||||
res.HitType = TRACE_HitFloor;
|
||||
if (res.CrossedWater == NULL &&
|
||||
CurSector->heightsec != NULL &&
|
||||
CurSector->heightsec->floorplane.ZatPoint (res.X, res.Y) >= res.Z)
|
||||
inf.CurSector->heightsec != NULL &&
|
||||
inf.CurSector->heightsec->floorplane.ZatPoint (res.X, res.Y) >= res.Z)
|
||||
{
|
||||
res.CrossedWater = CurSector;
|
||||
res.CrossedWater = inf.CurSector;
|
||||
}
|
||||
}
|
||||
else if (CheckSectorPlane (CurSector, false))
|
||||
else if (inf.CheckSectorPlane (inf.CurSector, false))
|
||||
{
|
||||
res.HitType = TRACE_HitCeiling;
|
||||
}
|
||||
|
@ -122,8 +130,13 @@ bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
|
|||
}
|
||||
}
|
||||
|
||||
static bool PTR_TraceIterator (intercept_t *in)
|
||||
bool FTraceInfo::TraceTraverse (int ptflags)
|
||||
{
|
||||
FPathTraverse it(StartX, StartY, StartX + FixedMul (Vx, MaxDist), StartY + FixedMul (Vy, MaxDist), ptflags);
|
||||
intercept_t *in;
|
||||
|
||||
while ((in = it.Next()))
|
||||
{
|
||||
fixed_t hitx, hity, hitz;
|
||||
fixed_t dist;
|
||||
|
||||
|
@ -133,8 +146,8 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
sector_t *entersector;
|
||||
|
||||
dist = FixedMul (MaxDist, in->frac);
|
||||
hitx = trace.x + FixedMul (Vx, dist);
|
||||
hity = trace.y + FixedMul (Vy, dist);
|
||||
hitx = StartX + FixedMul (Vx, dist);
|
||||
hity = StartY + FixedMul (Vy, dist);
|
||||
hitz = StartZ + FixedMul (Vz, dist);
|
||||
|
||||
fixed_t ff, fc, bf = 0, bc = 0;
|
||||
|
@ -156,7 +169,7 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
}
|
||||
else
|
||||
{
|
||||
lineside = P_PointOnLineSide (trace.x, trace.y, in->d.line);
|
||||
lineside = P_PointOnLineSide (StartX, StartY, in->d.line);
|
||||
CurSector = lineside ? in->d.line->backsector : in->d.line->frontsector;
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +186,7 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
// This is the way Doom.exe did it and some WADs (e.g. Alien Vendetta MAP15 need it.
|
||||
if (i_compatflags & COMPATF_TRACE && in->d.line->backsector == in->d.line->frontsector)
|
||||
{
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,12 +294,12 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
{
|
||||
CurSector = entersector;
|
||||
EnterDist = dist;
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TraceCallback != NULL)
|
||||
{
|
||||
return TraceCallback (*Results);
|
||||
if (!TraceCallback (*Results)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -298,48 +311,48 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
if (!(in->d.thing->flags & ActorMask) ||
|
||||
in->d.thing == IgnoreThis)
|
||||
{
|
||||
return true;
|
||||
continue;
|
||||
}
|
||||
|
||||
dist = FixedMul (MaxDist, in->frac);
|
||||
hitx = trace.x + FixedMul (Vx, dist);
|
||||
hity = trace.y + FixedMul (Vy, dist);
|
||||
hitx = StartX + FixedMul (Vx, dist);
|
||||
hity = StartY + FixedMul (Vy, dist);
|
||||
hitz = StartZ + FixedMul (Vz, dist);
|
||||
|
||||
if (hitz > in->d.thing->z + in->d.thing->height)
|
||||
{ // trace enters above actor
|
||||
if (Vz >= 0) return true; // Going up: can't hit
|
||||
if (Vz >= 0) continue; // Going up: can't hit
|
||||
|
||||
// Does it hit the top of the actor?
|
||||
dist = FixedDiv(in->d.thing->z + in->d.thing->height - StartZ, Vz);
|
||||
|
||||
if (dist > MaxDist) return true;
|
||||
if (dist > MaxDist) continue;
|
||||
in->frac = FixedDiv(dist, MaxDist);
|
||||
|
||||
hitx = trace.x + FixedMul (Vx, dist);
|
||||
hity = trace.y + FixedMul (Vy, dist);
|
||||
hitx = StartX + FixedMul (Vx, dist);
|
||||
hity = StartY + FixedMul (Vy, dist);
|
||||
hitz = StartZ + FixedMul (Vz, dist);
|
||||
|
||||
// calculated coordinate is outside the actor's bounding box
|
||||
if (abs(hitx - in->d.thing->x) > in->d.thing->radius ||
|
||||
abs(hity - in->d.thing->y) > in->d.thing->radius) return true;
|
||||
abs(hity - in->d.thing->y) > in->d.thing->radius) continue;
|
||||
}
|
||||
else if (hitz < in->d.thing->z)
|
||||
{ // trace enters below actor
|
||||
if (Vz <= 0) return true; // Going down: can't hit
|
||||
if (Vz <= 0) continue; // Going down: can't hit
|
||||
|
||||
// Does it hit the bottom of the actor?
|
||||
dist = FixedDiv(in->d.thing->z - StartZ, Vz);
|
||||
if (dist > MaxDist) return true;
|
||||
if (dist > MaxDist) continue;
|
||||
in->frac = FixedDiv(dist, MaxDist);
|
||||
|
||||
hitx = trace.x + FixedMul (Vx, dist);
|
||||
hity = trace.y + FixedMul (Vy, dist);
|
||||
hitx = StartX + FixedMul (Vx, dist);
|
||||
hity = StartY + FixedMul (Vy, dist);
|
||||
hitz = StartZ + FixedMul (Vz, dist);
|
||||
|
||||
// calculated coordinate is outside the actor's bounding box
|
||||
if (abs(hitx - in->d.thing->x) > in->d.thing->radius ||
|
||||
abs(hity - in->d.thing->y) > in->d.thing->radius) return true;
|
||||
abs(hity - in->d.thing->y) > in->d.thing->radius) continue;
|
||||
}
|
||||
|
||||
|
||||
|
@ -353,15 +366,17 @@ static bool PTR_TraceIterator (intercept_t *in)
|
|||
|
||||
if (TraceCallback != NULL)
|
||||
{
|
||||
return TraceCallback (*Results);
|
||||
if (!TraceCallback (*Results)) return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
||||
bool FTraceInfo::CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
||||
{
|
||||
secplane_t plane;
|
||||
|
||||
|
@ -378,16 +393,16 @@ static bool CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
|||
|
||||
if (den != 0)
|
||||
{
|
||||
fixed_t num = TMulScale16 (plane.a, trace.x,
|
||||
plane.b, trace.y,
|
||||
fixed_t num = TMulScale16 (plane.a, StartX,
|
||||
plane.b, StartY,
|
||||
plane.c, StartZ) + plane.d;
|
||||
|
||||
fixed_t hitdist = FixedDiv (-num, den);
|
||||
|
||||
if (hitdist > EnterDist && hitdist < MaxDist)
|
||||
{
|
||||
Results->X = trace.x + FixedMul (Vx, hitdist);
|
||||
Results->Y = trace.y + FixedMul (Vy, hitdist);
|
||||
Results->X = StartX + FixedMul (Vx, hitdist);
|
||||
Results->Y = StartY + FixedMul (Vy, hitdist);
|
||||
Results->Z = StartZ + FixedMul (Vz, hitdist);
|
||||
Results->Distance = hitdist;
|
||||
Results->Fraction = FixedDiv (hitdist, MaxDist);
|
||||
|
|
|
@ -1083,11 +1083,7 @@ void R_SetupFrame (AActor *actor)
|
|||
camera->sprite != 0) // Sprite 0 is always TNT1
|
||||
{
|
||||
// [RH] Use chasecam view
|
||||
P_AimCamera (camera);
|
||||
iview->nviewx = CameraX;
|
||||
iview->nviewy = CameraY;
|
||||
iview->nviewz = CameraZ;
|
||||
viewsector = CameraSector;
|
||||
P_AimCamera (camera, iview->nviewx, iview->nviewy, iview->nviewz, viewsector);
|
||||
r_showviewer = true;
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue