mirror of
https://github.com/ZDoom/qzdoom-gpl.git
synced 2025-01-18 21:21:36 +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)
|
April 9, 2008 (SBarInfo Update #17)
|
||||||
- Fixed: SBarInfo tried to calculate scaled offsets on unscaled status bars.
|
- 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
|
- Added: createpopup to SBarInfo. No we don't have custom popups yet. It only
|
||||||
|
|
143
src/b_func.cpp
143
src/b_func.cpp
|
@ -25,98 +25,87 @@
|
||||||
|
|
||||||
static FRandom pr_botdofire ("BotDoFire");
|
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)
|
||||||
{
|
{
|
||||||
fixed_t hitx, hity;
|
if (looker == rtarget)
|
||||||
fixed_t frac;
|
return false;
|
||||||
line_t *line;
|
|
||||||
AActor *thing;
|
|
||||||
fixed_t dist;
|
|
||||||
sector_t *s;
|
|
||||||
|
|
||||||
frac = in->frac - FixedDiv (4*FRACUNIT, MAX_TRAVERSE_DIST);
|
if ((rtarget->Sector->ceilingplane.ZatPoint (rtarget->x, rtarget->y) -
|
||||||
dist = FixedMul (frac, MAX_TRAVERSE_DIST);
|
rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y))
|
||||||
|
< looker->height) //Where rtarget is, looker can't be.
|
||||||
|
return false;
|
||||||
|
|
||||||
hitx = trace.x + FixedMul (looker->momx, frac);
|
sector_t *last_s = looker->Sector;
|
||||||
hity = trace.y + FixedMul (looker->momy, frac);
|
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;
|
||||||
|
|
||||||
if (in->isaline)
|
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()))
|
||||||
{
|
{
|
||||||
line = in->d.line;
|
fixed_t hitx, hity;
|
||||||
|
fixed_t frac;
|
||||||
|
line_t *line;
|
||||||
|
AActor *thing;
|
||||||
|
fixed_t dist;
|
||||||
|
sector_t *s;
|
||||||
|
|
||||||
if (!(line->flags & ML_TWOSIDED) || (line->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)))
|
frac = in->frac - FixedDiv (4*FRACUNIT, MAX_TRAVERSE_DIST);
|
||||||
{
|
dist = FixedMul (frac, MAX_TRAVERSE_DIST);
|
||||||
return (reachable = false); //Cannot continue.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Determine if going to use backsector/frontsector.
|
|
||||||
s = (line->backsector == last_s) ? line->frontsector : line->backsector;
|
|
||||||
fixed_t ceilingheight = s->ceilingplane.ZatPoint (hitx, hity);
|
|
||||||
fixed_t floorheight = s->floorplane.ZatPoint (hitx, hity);
|
|
||||||
|
|
||||||
if (!bglobal.IsDangerous (s) && //Any nukage/lava?
|
hitx = it.Trace().x + FixedMul (looker->momx, frac);
|
||||||
(floorheight <= (last_z+MAXMOVEHEIGHT)
|
hity = it.Trace().y + FixedMul (looker->momy, frac);
|
||||||
&& ((ceilingheight == floorheight && line->special)
|
|
||||||
|| (ceilingheight - floorheight) >= looker->height))) //Does it fit?
|
if (in->isaline)
|
||||||
|
{
|
||||||
|
line = in->d.line;
|
||||||
|
|
||||||
|
if (!(line->flags & ML_TWOSIDED) || (line->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING|ML_BLOCK_PLAYERS)))
|
||||||
{
|
{
|
||||||
last_z = floorheight;
|
return false; //Cannot continue.
|
||||||
last_s = s;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return (reachable = false);
|
//Determine if going to use backsector/frontsector.
|
||||||
|
s = (line->backsector == last_s) ? line->frontsector : line->backsector;
|
||||||
|
fixed_t ceilingheight = s->ceilingplane.ZatPoint (hitx, hity);
|
||||||
|
fixed_t floorheight = s->floorplane.ZatPoint (hitx, hity);
|
||||||
|
|
||||||
|
if (!bglobal.IsDangerous (s) && //Any nukage/lava?
|
||||||
|
(floorheight <= (last_z+MAXMOVEHEIGHT)
|
||||||
|
&& ((ceilingheight == floorheight && line->special)
|
||||||
|
|| (ceilingheight - floorheight) >= looker->height))) //Does it fit?
|
||||||
|
{
|
||||||
|
last_z = floorheight;
|
||||||
|
last_s = s;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dist > estimated_dist)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
thing = in->d.thing;
|
||||||
|
if (thing == looker) //Can't reach self in this case.
|
||||||
|
continue;
|
||||||
|
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y) <= (last_z+MAXMOVEHEIGHT)))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
reachable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dist > estimated_dist)
|
|
||||||
{
|
|
||||||
reachable = true;
|
|
||||||
return false; //Don't need to continue.
|
|
||||||
}
|
|
||||||
|
|
||||||
thing = in->d.thing;
|
|
||||||
if (thing == looker) //Can't reach self in this case.
|
|
||||||
return true;
|
|
||||||
if (thing == rtarget && (rtarget->Sector->floorplane.ZatPoint (rtarget->x, rtarget->y) <= (last_z+MAXMOVEHEIGHT)))
|
|
||||||
{
|
|
||||||
reachable = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return reachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,12 +40,59 @@ void FBoundingBox::AddToBox (fixed_t x, fixed_t y)
|
||||||
m_Box[BOXTOP] = 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
|
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
|
fixed_t frac; // along trace line
|
||||||
bool isaline;
|
bool isaline;
|
||||||
|
bool done;
|
||||||
union {
|
union {
|
||||||
AActor *thing;
|
AActor *thing;
|
||||||
line_t *line;
|
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);
|
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
|
struct FLineOpening
|
||||||
{
|
{
|
||||||
|
@ -255,10 +255,7 @@ public:
|
||||||
|
|
||||||
class FBlockThingsIterator
|
class FBlockThingsIterator
|
||||||
{
|
{
|
||||||
typedef TArray<AActor *> BTChecked;
|
static TArray<AActor *> CheckArray;
|
||||||
|
|
||||||
static TDeletingArray< BTChecked* > FreeBTChecked;
|
|
||||||
|
|
||||||
|
|
||||||
int minx, maxx;
|
int minx, maxx;
|
||||||
int miny, maxy;
|
int miny, maxy;
|
||||||
|
@ -266,21 +263,24 @@ class FBlockThingsIterator
|
||||||
int curx, cury;
|
int curx, cury;
|
||||||
|
|
||||||
bool dontfreecheck;
|
bool dontfreecheck;
|
||||||
BTChecked *checkarray;
|
int checkindex;
|
||||||
|
|
||||||
FBlockNode *block;
|
FBlockNode *block;
|
||||||
|
|
||||||
BTChecked *GetCheckArray();
|
|
||||||
void FreeCheckArray();
|
|
||||||
void StartBlock(int x, int y);
|
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:
|
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(const FBoundingBox &box);
|
||||||
~FBlockThingsIterator()
|
~FBlockThingsIterator();
|
||||||
{
|
|
||||||
if (!dontfreecheck) FreeCheckArray();
|
|
||||||
}
|
|
||||||
AActor *Next();
|
AActor *Next();
|
||||||
void Reset() { StartBlock(minx, miny); }
|
void Reset() { StartBlock(minx, miny); }
|
||||||
};
|
};
|
||||||
|
@ -293,20 +293,31 @@ public:
|
||||||
AActor *Next();
|
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_ADDLINES 1
|
||||||
#define PT_ADDTHINGS 2
|
#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_BlockmapSearch (AActor *origin, int distance, AActor *(*func)(AActor *, int));
|
||||||
AActor *P_RoughMonsterSearch (AActor *mo, int distance);
|
AActor *P_RoughMonsterSearch (AActor *mo, int distance);
|
||||||
|
|
||||||
|
@ -385,9 +396,7 @@ bool P_CheckMissileSpawn (AActor *missile);
|
||||||
void P_PlaySpawnSound(AActor *missile, AActor *spawner);
|
void P_PlaySpawnSound(AActor *missile, AActor *spawner);
|
||||||
|
|
||||||
// [RH] Position the chasecam
|
// [RH] Position the chasecam
|
||||||
void P_AimCamera (AActor *t1);
|
void P_AimCamera (AActor *t1, fixed_t &x, fixed_t &y, fixed_t &z, sector_t *&sec);
|
||||||
extern fixed_t CameraX, CameraY, CameraZ;
|
|
||||||
extern sector_t *CameraSector;
|
|
||||||
|
|
||||||
// [RH] Means of death
|
// [RH] Means of death
|
||||||
void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, bool hurtSelf, bool dodamage=true);
|
void P_RadiusAttack (AActor *spot, AActor *source, int damage, int distance, FName damageType, bool hurtSelf, bool dodamage=true);
|
||||||
|
|
968
src/p_map.cpp
968
src/p_map.cpp
File diff suppressed because it is too large
Load diff
279
src/p_maputl.cpp
279
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);
|
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
|
// P_InterceptVector
|
||||||
|
@ -264,6 +213,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef,
|
||||||
// THING POSITION SETTING
|
// THING POSITION SETTING
|
||||||
//
|
//
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// P_UnsetThingPosition
|
// P_UnsetThingPosition
|
||||||
// Unlinks a thing from block map and sectors.
|
// 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
|
// lookups maintaining lists of things inside
|
||||||
// these structures need to be updated.
|
// these structures need to be updated.
|
||||||
//
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
void AActor::UnlinkFromWorld ()
|
void AActor::UnlinkFromWorld ()
|
||||||
{
|
{
|
||||||
sector_list = NULL;
|
sector_list = NULL;
|
||||||
|
@ -326,11 +278,14 @@ void AActor::UnlinkFromWorld ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// P_SetThingPosition
|
// P_SetThingPosition
|
||||||
// Links a thing into both a block and a subsector based on it's x y.
|
// Links a thing into both a block and a subsector based on it's x y.
|
||||||
// Sets thing->sector properly
|
// Sets thing->sector properly
|
||||||
//
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
void AActor::LinkToWorld (bool buggy)
|
void AActor::LinkToWorld (bool buggy)
|
||||||
{
|
{
|
||||||
// link into subsector
|
// link into subsector
|
||||||
|
@ -433,12 +388,15 @@ void AActor::LinkToWorld (sector_t *sec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
//
|
//
|
||||||
// [RH] LinkToWorldForMapThing
|
// [RH] LinkToWorldForMapThing
|
||||||
//
|
//
|
||||||
// Emulate buggy PointOnLineSide and fix actors that lie on
|
// Emulate buggy PointOnLineSide and fix actors that lie on
|
||||||
// lines to compensate for some IWAD maps.
|
// lines to compensate for some IWAD maps.
|
||||||
//
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node)
|
static int R_PointOnSideSlow (fixed_t x, fixed_t y, node_t *node)
|
||||||
{
|
{
|
||||||
// [RH] This might have been faster than two multiplies and an
|
// [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
|
// Not inside the line's bounding box
|
||||||
if (x + radius <= ldef->bbox[BOXLEFT]
|
if (x + radius <= ldef->bbox[BOXLEFT]
|
||||||
|| x - radius >= ldef->bbox[BOXRIGHT]
|
|| x - radius >= ldef->bbox[BOXRIGHT]
|
||||||
|
@ -586,39 +543,6 @@ sector_t *AActor::LinkToWorldForMapThing ()
|
||||||
y += FixedMul(distance, finesine[finean]);
|
y += FixedMul(distance, finesine[finean]);
|
||||||
return P_PointInSector (x, y);
|
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;
|
return CheckArray.Size();
|
||||||
if (FreeBTChecked.Size() != 0)
|
|
||||||
{
|
|
||||||
BTChecked *ret;
|
|
||||||
FreeBTChecked.Pop(ret);
|
|
||||||
ret->Clear();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return new BTChecked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
void FBlockThingsIterator::SetCheckIndex(int newvalue)
|
||||||
//
|
|
||||||
// FBlockThingsIterator :: FreeCheckArray
|
|
||||||
//
|
|
||||||
//===========================================================================
|
|
||||||
|
|
||||||
void FBlockThingsIterator::FreeCheckArray()
|
|
||||||
{
|
{
|
||||||
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)
|
checkindex = check;
|
||||||
{
|
dontfreecheck = true;
|
||||||
checkarray = Check;
|
minx = maxx = x;
|
||||||
dontfreecheck = true;
|
miny = maxy = y;
|
||||||
}
|
Reset();
|
||||||
else
|
}
|
||||||
{
|
|
||||||
checkarray = GetCheckArray();
|
FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int _maxy)
|
||||||
}
|
{
|
||||||
|
checkindex = CheckArray.Size();
|
||||||
|
dontfreecheck = false;
|
||||||
minx = _minx;
|
minx = _minx;
|
||||||
maxx = _maxx;
|
maxx = _maxx;
|
||||||
miny = _miny;
|
miny = _miny;
|
||||||
|
@ -864,7 +776,8 @@ FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int
|
||||||
|
|
||||||
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
||||||
{
|
{
|
||||||
checkarray = GetCheckArray();
|
checkindex = CheckArray.Size();
|
||||||
|
dontfreecheck = false;
|
||||||
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
|
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||||
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
|
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||||
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
|
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||||
|
@ -872,6 +785,17 @@ FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
//
|
||||||
|
// FBlockThingsIterator :: FreeCheckArray
|
||||||
|
//
|
||||||
|
//===========================================================================
|
||||||
|
|
||||||
|
FBlockThingsIterator::~FBlockThingsIterator()
|
||||||
|
{
|
||||||
|
if (!dontfreecheck) CheckArray.Resize(checkindex);
|
||||||
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// FBlockThingsIterator :: StartBlock
|
// FBlockThingsIterator :: StartBlock
|
||||||
|
@ -910,16 +834,16 @@ AActor *FBlockThingsIterator::Next()
|
||||||
|
|
||||||
block = block->NextActor;
|
block = block->NextActor;
|
||||||
// Don't recheck things that were already checked
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i < 0)
|
if (i < checkindex)
|
||||||
{
|
{
|
||||||
checkarray->Push (me);
|
CheckArray.Push (me);
|
||||||
return me;
|
return me;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -967,16 +891,18 @@ AActor *FRadiusThingsIterator::Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// INTERCEPT ROUTINES
|
// FPathTraverse :: Intercepts
|
||||||
//
|
//
|
||||||
TArray<intercept_t> intercepts (128);
|
//===========================================================================
|
||||||
|
|
||||||
divline_t trace;
|
TArray<intercept_t> FPathTraverse::intercepts(128);
|
||||||
int ptflags;
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// PIT_AddLineIntercepts.
|
// FPathTraverse :: AddLineIntercepts.
|
||||||
// Looks for lines in the given block
|
// Looks for lines in the given block
|
||||||
// that intercept the given trace
|
// that intercept the given trace
|
||||||
// to add to the intercepts list.
|
// to add to the intercepts list.
|
||||||
|
@ -984,7 +910,9 @@ int ptflags;
|
||||||
// A line is crossed if its endpoints
|
// A line is crossed if its endpoints
|
||||||
// are on opposite sides of the trace.
|
// 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);
|
FBlockLinesIterator it(bx, by, bx, by, true);
|
||||||
line_t *ld;
|
line_t *ld;
|
||||||
|
@ -1023,18 +951,22 @@ void P_AddLineIntercepts(int bx, int by)
|
||||||
|
|
||||||
newintercept.frac = frac;
|
newintercept.frac = frac;
|
||||||
newintercept.isaline = true;
|
newintercept.isaline = true;
|
||||||
|
newintercept.done = false;
|
||||||
newintercept.d.line = ld;
|
newintercept.d.line = ld;
|
||||||
intercepts.Push (newintercept);
|
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;
|
AActor *thing;
|
||||||
|
|
||||||
while ((thing = it.Next()))
|
while ((thing = it.Next()))
|
||||||
|
@ -1099,6 +1031,7 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
||||||
intercept_t newintercept;
|
intercept_t newintercept;
|
||||||
newintercept.frac = frac;
|
newintercept.frac = frac;
|
||||||
newintercept.isaline = false;
|
newintercept.isaline = false;
|
||||||
|
newintercept.done = false;
|
||||||
newintercept.d.thing = thing;
|
newintercept.d.thing = thing;
|
||||||
intercepts.Push (newintercept);
|
intercepts.Push (newintercept);
|
||||||
continue;
|
continue;
|
||||||
|
@ -1113,6 +1046,7 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
||||||
intercept_t newintercept;
|
intercept_t newintercept;
|
||||||
newintercept.frac = 0;
|
newintercept.frac = 0;
|
||||||
newintercept.isaline = false;
|
newintercept.isaline = false;
|
||||||
|
newintercept.done = false;
|
||||||
newintercept.d.thing = thing;
|
newintercept.d.thing = thing;
|
||||||
intercepts.Push (newintercept);
|
intercepts.Push (newintercept);
|
||||||
}
|
}
|
||||||
|
@ -1120,60 +1054,41 @@ void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// P_TraverseIntercepts
|
// FPathTraverse :: Next
|
||||||
// Returns true if the traverser function returns true
|
|
||||||
// for all lines.
|
|
||||||
//
|
//
|
||||||
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;
|
intercept_t *in = NULL;
|
||||||
|
|
||||||
count = intercepts.Size ();
|
fixed_t dist = FIXED_MAX;
|
||||||
|
for (unsigned scanpos = intercept_index; scanpos < intercepts.Size (); scanpos++)
|
||||||
while (count--)
|
|
||||||
{
|
{
|
||||||
dist = FIXED_MAX;
|
intercept_t *scan = &intercepts[scanpos];
|
||||||
for (scanpos = 0; scanpos < intercepts.Size (); scanpos++)
|
if (scan->frac < dist && !scan->done)
|
||||||
{
|
{
|
||||||
scan = &intercepts[scanpos];
|
dist = scan->frac;
|
||||||
if (scan->frac < dist)
|
in = scan;
|
||||||
{
|
|
||||||
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,
|
// 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 xt1;
|
||||||
fixed_t yt1;
|
fixed_t yt1;
|
||||||
fixed_t xt2;
|
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;
|
int count;
|
||||||
|
|
||||||
validcount++;
|
validcount++;
|
||||||
intercepts.Clear ();
|
intercept_index = intercepts.Size();
|
||||||
pathbt.Clear ();
|
|
||||||
|
|
||||||
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
if ( ((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0)
|
||||||
x1 += FRACUNIT; // don't side exactly on a line
|
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;
|
mapx = xt1;
|
||||||
mapy = yt1;
|
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++)
|
for (count = 0 ; count < 100 ; count++)
|
||||||
{
|
{
|
||||||
if (flags & PT_ADDLINES)
|
if (flags & PT_ADDLINES)
|
||||||
{
|
{
|
||||||
P_AddLineIntercepts(mapx, mapy);
|
AddLineIntercepts(mapx, mapy);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PT_ADDTHINGS)
|
if (flags & PT_ADDTHINGS)
|
||||||
{
|
{
|
||||||
P_AddThingIntercepts(mapx, mapy, pathbt);
|
AddThingIntercepts(mapx, mapy, BTI_CheckIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mapx == xt2 && mapy == yt2)
|
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.
|
// be checked.
|
||||||
if (flags & PT_ADDLINES)
|
if (flags & PT_ADDLINES)
|
||||||
{
|
{
|
||||||
P_AddLineIntercepts(mapx + mapxstep, mapy);
|
AddLineIntercepts(mapx + mapxstep, mapy);
|
||||||
P_AddLineIntercepts(mapx, mapy + mapystep);
|
AddLineIntercepts(mapx, mapy + mapystep);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PT_ADDTHINGS)
|
if (flags & PT_ADDTHINGS)
|
||||||
{
|
{
|
||||||
P_AddThingIntercepts(mapx + mapxstep, mapy, pathbt);
|
AddThingIntercepts(mapx + mapxstep, mapy, BTI_CheckIndex);
|
||||||
P_AddThingIntercepts(mapx, mapy + mapystep, pathbt);
|
AddThingIntercepts(mapx, mapy + mapystep, BTI_CheckIndex);
|
||||||
}
|
}
|
||||||
xintercept += xstep;
|
xintercept += xstep;
|
||||||
yintercept += ystep;
|
yintercept += ystep;
|
||||||
|
@ -1345,10 +1261,16 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// go through the sorted list
|
FBlockThingsIterator::SetCheckIndex(BTI_CheckIndex);
|
||||||
return P_TraverseIntercepts ( trav, FRACUNIT );
|
maxfrac = FRACUNIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FPathTraverse::~FPathTraverse()
|
||||||
|
{
|
||||||
|
intercepts.Resize(intercept_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
//
|
//
|
||||||
// P_RoughMonsterSearch
|
// P_RoughMonsterSearch
|
||||||
|
@ -1473,4 +1395,3 @@ static AActor *RoughBlockCheck (AActor *mo, int index)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,6 @@ static void PlayerLandedOnThing (AActor *mo, AActor *onmobj);
|
||||||
|
|
||||||
extern cycle_t BotSupportCycles;
|
extern cycle_t BotSupportCycles;
|
||||||
extern cycle_t BotWTG;
|
extern cycle_t BotWTG;
|
||||||
extern fixed_t attackrange;
|
|
||||||
EXTERN_CVAR (Bool, r_drawfuzz);
|
EXTERN_CVAR (Bool, r_drawfuzz);
|
||||||
EXTERN_CVAR (Int, cl_rockettrails)
|
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 sightzstart; // eye z of looker
|
||||||
static fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
static fixed_t topslope, bottomslope; // slopes to top and bottom of target
|
||||||
static int SeePastBlockEverything, SeePastShootableLines;
|
static int SeePastBlockEverything, SeePastShootableLines;
|
||||||
|
|
499
src/p_trace.cpp
499
src/p_trace.cpp
|
@ -36,21 +36,26 @@
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
|
|
||||||
static fixed_t StartZ;
|
struct FTraceInfo
|
||||||
static fixed_t Vx, Vy, Vz;
|
{
|
||||||
static DWORD ActorMask, WallMask;
|
fixed_t StartX, StartY, StartZ;
|
||||||
static AActor *IgnoreThis;
|
fixed_t Vx, Vy, Vz;
|
||||||
static FTraceResults *Results;
|
DWORD ActorMask, WallMask;
|
||||||
static sector_t *CurSector;
|
AActor *IgnoreThis;
|
||||||
static fixed_t MaxDist;
|
FTraceResults *Results;
|
||||||
static fixed_t EnterDist;
|
sector_t *CurSector;
|
||||||
static bool (*TraceCallback)(FTraceResults &res);
|
fixed_t MaxDist;
|
||||||
static DWORD TraceFlags;
|
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);
|
static bool EditTraceResult (DWORD flags, FTraceResults &res);
|
||||||
|
|
||||||
|
|
||||||
bool Trace (fixed_t x, fixed_t y, fixed_t z, sector_t *sector,
|
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,
|
fixed_t vx, fixed_t vy, fixed_t vz, fixed_t maxDist,
|
||||||
DWORD actorMask, DWORD wallMask, AActor *ignore,
|
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))
|
DWORD flags, bool (*callback)(FTraceResults &res))
|
||||||
{
|
{
|
||||||
int ptflags;
|
int ptflags;
|
||||||
|
FTraceInfo inf;
|
||||||
|
|
||||||
ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS : PT_ADDLINES;
|
ptflags = actorMask ? PT_ADDLINES|PT_ADDTHINGS : PT_ADDLINES;
|
||||||
|
|
||||||
StartZ = z;
|
inf.StartX = x;
|
||||||
Vx = vx;
|
inf.StartY = y;
|
||||||
Vy = vy;
|
inf.StartZ = z;
|
||||||
Vz = vz;
|
inf.Vx = vx;
|
||||||
ActorMask = actorMask;
|
inf.Vy = vy;
|
||||||
WallMask = wallMask;
|
inf.Vz = vz;
|
||||||
IgnoreThis = ignore;
|
inf.ActorMask = actorMask;
|
||||||
CurSector = sector;
|
inf.WallMask = wallMask;
|
||||||
MaxDist = maxDist;
|
inf.IgnoreThis = ignore;
|
||||||
EnterDist = 0;
|
inf.CurSector = sector;
|
||||||
TraceCallback = callback;
|
inf.MaxDist = maxDist;
|
||||||
TraceFlags = flags;
|
inf.EnterDist = 0;
|
||||||
|
inf.TraceCallback = callback;
|
||||||
|
inf.TraceFlags = flags;
|
||||||
res.CrossedWater = NULL;
|
res.CrossedWater = NULL;
|
||||||
Results = &res;
|
inf.Results = &res;
|
||||||
|
|
||||||
res.HitType = TRACE_HitNone;
|
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;
|
res.HitType = TRACE_HitFloor;
|
||||||
if (res.CrossedWater == NULL &&
|
if (res.CrossedWater == NULL &&
|
||||||
CurSector->heightsec != NULL &&
|
inf.CurSector->heightsec != NULL &&
|
||||||
CurSector->heightsec->floorplane.ZatPoint (res.X, res.Y) >= res.Z)
|
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;
|
res.HitType = TRACE_HitCeiling;
|
||||||
}
|
}
|
||||||
|
@ -122,246 +130,253 @@ 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)
|
||||||
{
|
{
|
||||||
fixed_t hitx, hity, hitz;
|
FPathTraverse it(StartX, StartY, StartX + FixedMul (Vx, MaxDist), StartY + FixedMul (Vy, MaxDist), ptflags);
|
||||||
fixed_t dist;
|
intercept_t *in;
|
||||||
|
|
||||||
if (in->isaline)
|
while ((in = it.Next()))
|
||||||
{
|
{
|
||||||
int lineside;
|
fixed_t hitx, hity, hitz;
|
||||||
sector_t *entersector;
|
fixed_t dist;
|
||||||
|
|
||||||
dist = FixedMul (MaxDist, in->frac);
|
if (in->isaline)
|
||||||
hitx = trace.x + FixedMul (Vx, dist);
|
|
||||||
hity = trace.y + FixedMul (Vy, dist);
|
|
||||||
hitz = StartZ + FixedMul (Vz, dist);
|
|
||||||
|
|
||||||
fixed_t ff, fc, bf = 0, bc = 0;
|
|
||||||
|
|
||||||
if (in->d.line->frontsector == CurSector)
|
|
||||||
{
|
{
|
||||||
lineside = 0;
|
int lineside;
|
||||||
}
|
sector_t *entersector;
|
||||||
else if (in->d.line->backsector == CurSector)
|
|
||||||
{
|
dist = FixedMul (MaxDist, in->frac);
|
||||||
lineside = 1;
|
hitx = StartX + FixedMul (Vx, dist);
|
||||||
}
|
hity = StartY + FixedMul (Vy, dist);
|
||||||
else
|
hitz = StartZ + FixedMul (Vz, dist);
|
||||||
{ // Dammit. Why does Doom have to allow non-closed sectors?
|
|
||||||
if (in->d.line->backsector == NULL)
|
fixed_t ff, fc, bf = 0, bc = 0;
|
||||||
|
|
||||||
|
if (in->d.line->frontsector == CurSector)
|
||||||
{
|
{
|
||||||
lineside = 0;
|
lineside = 0;
|
||||||
CurSector = in->d.line->frontsector;
|
}
|
||||||
|
else if (in->d.line->backsector == CurSector)
|
||||||
|
{
|
||||||
|
lineside = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{ // Dammit. Why does Doom have to allow non-closed sectors?
|
||||||
lineside = P_PointOnLineSide (trace.x, trace.y, in->d.line);
|
if (in->d.line->backsector == NULL)
|
||||||
CurSector = lineside ? in->d.line->backsector : in->d.line->frontsector;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(in->d.line->flags & ML_TWOSIDED))
|
|
||||||
{
|
|
||||||
entersector = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entersector = (lineside == 0) ? in->d.line->backsector : in->d.line->frontsector;
|
|
||||||
|
|
||||||
// For backwards compatibility: Ignore lines with the same sector on both sides.
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ff = CurSector->floorplane.ZatPoint (hitx, hity);
|
|
||||||
fc = CurSector->ceilingplane.ZatPoint (hitx, hity);
|
|
||||||
|
|
||||||
if (entersector != NULL)
|
|
||||||
{
|
|
||||||
bf = entersector->floorplane.ZatPoint (hitx, hity);
|
|
||||||
bc = entersector->ceilingplane.ZatPoint (hitx, hity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Results->CrossedWater == NULL &&
|
|
||||||
CurSector->heightsec &&
|
|
||||||
!(CurSector->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
|
||||||
//CurSector->heightsec->waterzone &&
|
|
||||||
hitz <= CurSector->heightsec->floorplane.ZatPoint (hitx, hity))
|
|
||||||
{
|
|
||||||
// hit crossed a water plane
|
|
||||||
Results->CrossedWater = CurSector;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hitz <= ff)
|
|
||||||
{ // hit floor in front of wall
|
|
||||||
Results->HitType = TRACE_HitFloor;
|
|
||||||
}
|
|
||||||
else if (hitz >= fc)
|
|
||||||
{ // hit ceiling in front of wall
|
|
||||||
Results->HitType = TRACE_HitCeiling;
|
|
||||||
}
|
|
||||||
else if (entersector == NULL ||
|
|
||||||
hitz <= bf || hitz >= bc ||
|
|
||||||
in->d.line->flags & WallMask)
|
|
||||||
{ // hit the wall
|
|
||||||
Results->HitType = TRACE_HitWall;
|
|
||||||
Results->Tier =
|
|
||||||
entersector == NULL ? TIER_Middle :
|
|
||||||
hitz <= bf ? TIER_Lower :
|
|
||||||
hitz >= bc ? TIER_Upper : TIER_Middle;
|
|
||||||
if (TraceFlags & TRACE_Impact)
|
|
||||||
{
|
|
||||||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{ // made it past the wall
|
|
||||||
Results->HitType = TRACE_HitNone;
|
|
||||||
if (TraceFlags & TRACE_PCross)
|
|
||||||
{
|
|
||||||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_PCROSS);
|
|
||||||
}
|
|
||||||
if (TraceFlags & TRACE_Impact)
|
|
||||||
{ // This is incorrect for "impact", but Hexen did this, so
|
|
||||||
// we need to as well, for compatibility
|
|
||||||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Results->HitType != TRACE_HitNone)
|
|
||||||
{
|
|
||||||
// We hit something, so figure out where exactly
|
|
||||||
Results->Sector = CurSector;
|
|
||||||
|
|
||||||
if (Results->HitType != TRACE_HitWall &&
|
|
||||||
!CheckSectorPlane (CurSector, Results->HitType == TRACE_HitFloor))
|
|
||||||
{ // trace is parallel to the plane (or right on it)
|
|
||||||
if (entersector == NULL)
|
|
||||||
{
|
{
|
||||||
Results->HitType = TRACE_HitWall;
|
lineside = 0;
|
||||||
Results->Tier = TIER_Middle;
|
CurSector = in->d.line->frontsector;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (hitz <= bf || hitz >= bc)
|
lineside = P_PointOnLineSide (StartX, StartY, in->d.line);
|
||||||
{
|
CurSector = lineside ? in->d.line->backsector : in->d.line->frontsector;
|
||||||
Results->HitType = TRACE_HitWall;
|
|
||||||
Results->Tier =
|
|
||||||
hitz <= bf ? TIER_Lower :
|
|
||||||
hitz >= bc ? TIER_Upper : TIER_Middle;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Results->HitType = TRACE_HitNone;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (Results->HitType == TRACE_HitWall && TraceFlags & TRACE_Impact)
|
}
|
||||||
|
|
||||||
|
if (!(in->d.line->flags & ML_TWOSIDED))
|
||||||
|
{
|
||||||
|
entersector = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entersector = (lineside == 0) ? in->d.line->backsector : in->d.line->frontsector;
|
||||||
|
|
||||||
|
// For backwards compatibility: Ignore lines with the same sector on both sides.
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ff = CurSector->floorplane.ZatPoint (hitx, hity);
|
||||||
|
fc = CurSector->ceilingplane.ZatPoint (hitx, hity);
|
||||||
|
|
||||||
|
if (entersector != NULL)
|
||||||
|
{
|
||||||
|
bf = entersector->floorplane.ZatPoint (hitx, hity);
|
||||||
|
bc = entersector->ceilingplane.ZatPoint (hitx, hity);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Results->CrossedWater == NULL &&
|
||||||
|
CurSector->heightsec &&
|
||||||
|
!(CurSector->MoreFlags & SECF_IGNOREHEIGHTSEC) &&
|
||||||
|
//CurSector->heightsec->waterzone &&
|
||||||
|
hitz <= CurSector->heightsec->floorplane.ZatPoint (hitx, hity))
|
||||||
|
{
|
||||||
|
// hit crossed a water plane
|
||||||
|
Results->CrossedWater = CurSector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hitz <= ff)
|
||||||
|
{ // hit floor in front of wall
|
||||||
|
Results->HitType = TRACE_HitFloor;
|
||||||
|
}
|
||||||
|
else if (hitz >= fc)
|
||||||
|
{ // hit ceiling in front of wall
|
||||||
|
Results->HitType = TRACE_HitCeiling;
|
||||||
|
}
|
||||||
|
else if (entersector == NULL ||
|
||||||
|
hitz <= bf || hitz >= bc ||
|
||||||
|
in->d.line->flags & WallMask)
|
||||||
|
{ // hit the wall
|
||||||
|
Results->HitType = TRACE_HitWall;
|
||||||
|
Results->Tier =
|
||||||
|
entersector == NULL ? TIER_Middle :
|
||||||
|
hitz <= bf ? TIER_Lower :
|
||||||
|
hitz >= bc ? TIER_Upper : TIER_Middle;
|
||||||
|
if (TraceFlags & TRACE_Impact)
|
||||||
{
|
{
|
||||||
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{ // made it past the wall
|
||||||
|
Results->HitType = TRACE_HitNone;
|
||||||
|
if (TraceFlags & TRACE_PCross)
|
||||||
|
{
|
||||||
|
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_PCROSS);
|
||||||
|
}
|
||||||
|
if (TraceFlags & TRACE_Impact)
|
||||||
|
{ // This is incorrect for "impact", but Hexen did this, so
|
||||||
|
// we need to as well, for compatibility
|
||||||
|
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Results->HitType == TRACE_HitWall)
|
if (Results->HitType != TRACE_HitNone)
|
||||||
{
|
{
|
||||||
Results->X = hitx;
|
// We hit something, so figure out where exactly
|
||||||
Results->Y = hity;
|
Results->Sector = CurSector;
|
||||||
Results->Z = hitz;
|
|
||||||
Results->Distance = dist;
|
if (Results->HitType != TRACE_HitWall &&
|
||||||
Results->Fraction = in->frac;
|
!CheckSectorPlane (CurSector, Results->HitType == TRACE_HitFloor))
|
||||||
Results->Line = in->d.line;
|
{ // trace is parallel to the plane (or right on it)
|
||||||
Results->Side = lineside;
|
if (entersector == NULL)
|
||||||
|
{
|
||||||
|
Results->HitType = TRACE_HitWall;
|
||||||
|
Results->Tier = TIER_Middle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (hitz <= bf || hitz >= bc)
|
||||||
|
{
|
||||||
|
Results->HitType = TRACE_HitWall;
|
||||||
|
Results->Tier =
|
||||||
|
hitz <= bf ? TIER_Lower :
|
||||||
|
hitz >= bc ? TIER_Upper : TIER_Middle;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Results->HitType = TRACE_HitNone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Results->HitType == TRACE_HitWall && TraceFlags & TRACE_Impact)
|
||||||
|
{
|
||||||
|
P_ActivateLine (in->d.line, IgnoreThis, lineside, SPAC_IMPACT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Results->HitType == TRACE_HitWall)
|
||||||
|
{
|
||||||
|
Results->X = hitx;
|
||||||
|
Results->Y = hity;
|
||||||
|
Results->Z = hitz;
|
||||||
|
Results->Distance = dist;
|
||||||
|
Results->Fraction = in->frac;
|
||||||
|
Results->Line = in->d.line;
|
||||||
|
Results->Side = lineside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Results->HitType == TRACE_HitNone)
|
||||||
|
{
|
||||||
|
CurSector = entersector;
|
||||||
|
EnterDist = dist;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TraceCallback != NULL)
|
||||||
|
{
|
||||||
|
if (!TraceCallback (*Results)) return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Results->HitType == TRACE_HitNone)
|
// Encountered an actor
|
||||||
|
if (!(in->d.thing->flags & ActorMask) ||
|
||||||
|
in->d.thing == IgnoreThis)
|
||||||
{
|
{
|
||||||
CurSector = entersector;
|
continue;
|
||||||
EnterDist = dist;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dist = FixedMul (MaxDist, in->frac);
|
||||||
|
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) 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) continue;
|
||||||
|
in->frac = FixedDiv(dist, MaxDist);
|
||||||
|
|
||||||
|
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) continue;
|
||||||
|
}
|
||||||
|
else if (hitz < in->d.thing->z)
|
||||||
|
{ // trace enters below actor
|
||||||
|
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) continue;
|
||||||
|
in->frac = FixedDiv(dist, MaxDist);
|
||||||
|
|
||||||
|
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) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Results->HitType = TRACE_HitActor;
|
||||||
|
Results->X = hitx;
|
||||||
|
Results->Y = hity;
|
||||||
|
Results->Z = hitz;
|
||||||
|
Results->Distance = dist;
|
||||||
|
Results->Fraction = in->frac;
|
||||||
|
Results->Actor = in->d.thing;
|
||||||
|
|
||||||
if (TraceCallback != NULL)
|
if (TraceCallback != NULL)
|
||||||
{
|
{
|
||||||
return TraceCallback (*Results);
|
if (!TraceCallback (*Results)) return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// Encountered an actor
|
|
||||||
if (!(in->d.thing->flags & ActorMask) ||
|
|
||||||
in->d.thing == IgnoreThis)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
dist = FixedMul (MaxDist, in->frac);
|
|
||||||
hitx = trace.x + FixedMul (Vx, dist);
|
|
||||||
hity = trace.y + 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
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
in->frac = FixedDiv(dist, MaxDist);
|
|
||||||
|
|
||||||
hitx = trace.x + FixedMul (Vx, dist);
|
|
||||||
hity = trace.y + 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;
|
|
||||||
}
|
|
||||||
else if (hitz < in->d.thing->z)
|
|
||||||
{ // trace enters below actor
|
|
||||||
if (Vz <= 0) return true; // 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;
|
|
||||||
in->frac = FixedDiv(dist, MaxDist);
|
|
||||||
|
|
||||||
hitx = trace.x + FixedMul (Vx, dist);
|
|
||||||
hity = trace.y + 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Results->HitType = TRACE_HitActor;
|
|
||||||
Results->X = hitx;
|
|
||||||
Results->Y = hity;
|
|
||||||
Results->Z = hitz;
|
|
||||||
Results->Distance = dist;
|
|
||||||
Results->Fraction = in->frac;
|
|
||||||
Results->Actor = in->d.thing;
|
|
||||||
|
|
||||||
if (TraceCallback != NULL)
|
|
||||||
{
|
|
||||||
return TraceCallback (*Results);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
bool FTraceInfo::CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
||||||
{
|
{
|
||||||
secplane_t plane;
|
secplane_t plane;
|
||||||
|
|
||||||
|
@ -378,16 +393,16 @@ static bool CheckSectorPlane (const sector_t *sector, bool checkFloor)
|
||||||
|
|
||||||
if (den != 0)
|
if (den != 0)
|
||||||
{
|
{
|
||||||
fixed_t num = TMulScale16 (plane.a, trace.x,
|
fixed_t num = TMulScale16 (plane.a, StartX,
|
||||||
plane.b, trace.y,
|
plane.b, StartY,
|
||||||
plane.c, StartZ) + plane.d;
|
plane.c, StartZ) + plane.d;
|
||||||
|
|
||||||
fixed_t hitdist = FixedDiv (-num, den);
|
fixed_t hitdist = FixedDiv (-num, den);
|
||||||
|
|
||||||
if (hitdist > EnterDist && hitdist < MaxDist)
|
if (hitdist > EnterDist && hitdist < MaxDist)
|
||||||
{
|
{
|
||||||
Results->X = trace.x + FixedMul (Vx, hitdist);
|
Results->X = StartX + FixedMul (Vx, hitdist);
|
||||||
Results->Y = trace.y + FixedMul (Vy, hitdist);
|
Results->Y = StartY + FixedMul (Vy, hitdist);
|
||||||
Results->Z = StartZ + FixedMul (Vz, hitdist);
|
Results->Z = StartZ + FixedMul (Vz, hitdist);
|
||||||
Results->Distance = hitdist;
|
Results->Distance = hitdist;
|
||||||
Results->Fraction = FixedDiv (hitdist, MaxDist);
|
Results->Fraction = FixedDiv (hitdist, MaxDist);
|
||||||
|
|
|
@ -1083,11 +1083,7 @@ void R_SetupFrame (AActor *actor)
|
||||||
camera->sprite != 0) // Sprite 0 is always TNT1
|
camera->sprite != 0) // Sprite 0 is always TNT1
|
||||||
{
|
{
|
||||||
// [RH] Use chasecam view
|
// [RH] Use chasecam view
|
||||||
P_AimCamera (camera);
|
P_AimCamera (camera, iview->nviewx, iview->nviewy, iview->nviewz, viewsector);
|
||||||
iview->nviewx = CameraX;
|
|
||||||
iview->nviewy = CameraY;
|
|
||||||
iview->nviewz = CameraZ;
|
|
||||||
viewsector = CameraSector;
|
|
||||||
r_showviewer = true;
|
r_showviewer = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue