mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
- Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but
P_FindFloorCeiling never did that. - Merged Check_Sides and PIT_CrossLine into A_PainShootSkull. - Replaced P_BlockLinesIterator with FBlockLinesIterator in all places it was used. This also allowed to remove all the global variable saving in P_CreateSecNodeList. - Added a new FBlockLinesIterator class that doesn't need a callback function because debugging the previous bug proved to be a bit annoying because it involved a P_BlockLinesIterator loop. - Fixed: The MBF code to move monsters away from dropoffs did not work as intended due to some random decisions in P_DoNewChaseDir. When in the avoiding dropoff mode these are ignored now. This should cure the problem that monsters hanging over a dropoff tended to drop down. SVN r887 (trunk)
This commit is contained in:
parent
d938121378
commit
ebd17de30a
16 changed files with 400 additions and 431 deletions
|
@ -1,4 +1,17 @@
|
||||||
April 6, 2008 (Changes by Graf Zahl)
|
April 6, 2008 (Changes by Graf Zahl)
|
||||||
|
- Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but
|
||||||
|
P_FindFloorCeiling never did that.
|
||||||
|
- Merged Check_Sides and PIT_CrossLine into A_PainShootSkull.
|
||||||
|
- Replaced P_BlockLinesIterator with FBlockLinesIterator in all places it was
|
||||||
|
used. This also allowed to remove all the global variable saving in
|
||||||
|
P_CreateSecNodeList.
|
||||||
|
- Added a new FBlockLinesIterator class that doesn't need a callback
|
||||||
|
function because debugging the previous bug proved to be a bit annoying
|
||||||
|
because it involved a P_BlockLinesIterator loop.
|
||||||
|
- Fixed: The MBF code to move monsters away from dropoffs did not work as
|
||||||
|
intended due to some random decisions in P_DoNewChaseDir. When in the
|
||||||
|
avoiding dropoff mode these are ignored now. This should cure the problem
|
||||||
|
that monsters hanging over a dropoff tended to drop down.
|
||||||
- Added a NOTIMEFREEZE flag that excludes actors from being affected by
|
- Added a NOTIMEFREEZE flag that excludes actors from being affected by
|
||||||
the time freezer powerup.
|
the time freezer powerup.
|
||||||
- Changed: Empty pickup messages are no longer printed.
|
- Changed: Empty pickup messages are no longer printed.
|
||||||
|
|
|
@ -124,6 +124,17 @@ typedef struct _GUID
|
||||||
} GUID;
|
} GUID;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Bounding box coordinate storage.
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
BOXTOP,
|
||||||
|
BOXBOTTOM,
|
||||||
|
BOXLEFT,
|
||||||
|
BOXRIGHT
|
||||||
|
}; // bbox coordinates
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Fixed point, 32bit as 16.16.
|
// Fixed point, 32bit as 16.16.
|
||||||
//
|
//
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
#include "a_doomglobal.h"
|
#include "a_doomglobal.h"
|
||||||
#include "a_action.h"
|
#include "a_action.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "m_bbox.h"
|
||||||
#include "thingdef/thingdef.h"
|
#include "thingdef/thingdef.h"
|
||||||
|
|
||||||
void A_PainAttack (AActor *);
|
void A_PainAttack (AActor *);
|
||||||
|
@ -23,6 +25,7 @@ static const PClass *GetSpawnType()
|
||||||
return spawntype;
|
return spawntype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// A_PainShootSkull
|
// A_PainShootSkull
|
||||||
// Spawn a lost soul and launch it at the target
|
// Spawn a lost soul and launch it at the target
|
||||||
|
@ -80,9 +83,24 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype)
|
||||||
// wall or an impassible line, or a "monsters can't cross" line.// |
|
// wall or an impassible line, or a "monsters can't cross" line.// |
|
||||||
// If it is, then we don't allow the spawn. // V
|
// If it is, then we don't allow the spawn. // V
|
||||||
|
|
||||||
if (Check_Sides (self, x, y))
|
FBoundingBox box(MIN(self->x, x), MIN(self->y, y), MAX(self->x, x), MAX(self->y, y));
|
||||||
|
FBlockLinesIterator it(box);
|
||||||
|
line_t *ld;
|
||||||
|
|
||||||
|
while ((ld = it.Next()))
|
||||||
{
|
{
|
||||||
return;
|
if (!(ld->flags & ML_TWOSIDED) ||
|
||||||
|
(ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_BLOCKEVERYTHING)))
|
||||||
|
{
|
||||||
|
if (!(box.Left() > ld->bbox[BOXRIGHT] ||
|
||||||
|
box.Right() < ld->bbox[BOXLEFT] ||
|
||||||
|
box.Top() < ld->bbox[BOXBOTTOM] ||
|
||||||
|
box.Bottom() > ld->bbox[BOXTOP]))
|
||||||
|
{
|
||||||
|
if (P_PointOnLineSide(self->x,self->y,ld) != P_PointOnLineSide(x,y,ld))
|
||||||
|
return; // line blocks trajectory // ^
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
other = Spawn (spawntype, x, y, z, ALLOW_REPLACE);
|
other = Spawn (spawntype, x, y, z, ALLOW_REPLACE);
|
||||||
|
|
|
@ -41,6 +41,7 @@ bool AArtiTomeOfPower::Use (bool pickup)
|
||||||
else
|
else
|
||||||
{ // Succeeded
|
{ // Succeeded
|
||||||
Owner->player->morphTics = 0;
|
Owner->player->morphTics = 0;
|
||||||
|
Owner->player->MorphedPlayerClass = 0;
|
||||||
S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_IDLE);
|
S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_IDLE);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -199,6 +199,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
||||||
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
|
mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST);
|
||||||
|
|
||||||
player->morphTics = 0;
|
player->morphTics = 0;
|
||||||
|
player->MorphedPlayerClass = 0;
|
||||||
player->viewheight = mo->ViewHeight;
|
player->viewheight = mo->ViewHeight;
|
||||||
AInventory *level2 = mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2));
|
AInventory *level2 = mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2));
|
||||||
if (level2 != NULL)
|
if (level2 != NULL)
|
||||||
|
|
|
@ -25,17 +25,7 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#include "m_bbox.h"
|
#include "m_bbox.h"
|
||||||
|
#include "p_local.h"
|
||||||
FBoundingBox::FBoundingBox ()
|
|
||||||
{
|
|
||||||
ClearBox ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBoundingBox::ClearBox ()
|
|
||||||
{
|
|
||||||
m_Box[BOXTOP] = m_Box[BOXRIGHT] = FIXED_MIN;
|
|
||||||
m_Box[BOXBOTTOM] = m_Box[BOXLEFT] = FIXED_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FBoundingBox::AddToBox (fixed_t x, fixed_t y)
|
void FBoundingBox::AddToBox (fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
|
@ -50,6 +40,11 @@ void FBoundingBox::AddToBox (fixed_t x, fixed_t y)
|
||||||
m_Box[BOXTOP] = y;
|
m_Box[BOXTOP] = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int FBoundingBox::BoxOnLineSide (const line_t *ld) const
|
||||||
|
{
|
||||||
|
return P_BoxOnLineSide(m_Box, ld);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
49
src/m_bbox.h
49
src/m_bbox.h
|
@ -25,29 +25,46 @@
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
#include "m_fixed.h"
|
#include "m_fixed.h"
|
||||||
|
|
||||||
|
struct line_t;
|
||||||
// Bounding box coordinate storage.
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
BOXTOP,
|
|
||||||
BOXBOTTOM,
|
|
||||||
BOXLEFT,
|
|
||||||
BOXRIGHT
|
|
||||||
}; // bbox coordinates
|
|
||||||
|
|
||||||
|
|
||||||
class FBoundingBox
|
class FBoundingBox
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FBoundingBox();
|
FBoundingBox()
|
||||||
|
{
|
||||||
|
ClearBox();
|
||||||
|
}
|
||||||
|
|
||||||
|
FBoundingBox(fixed_t left, fixed_t bottom, fixed_t right, fixed_t top)
|
||||||
|
{
|
||||||
|
m_Box[BOXTOP] = top;
|
||||||
|
m_Box[BOXLEFT] = left;
|
||||||
|
m_Box[BOXRIGHT] = right;
|
||||||
|
m_Box[BOXBOTTOM] = bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
FBoundingBox(fixed_t x, fixed_t y, fixed_t radius)
|
||||||
|
{
|
||||||
|
m_Box[BOXTOP] = y + radius;
|
||||||
|
m_Box[BOXLEFT] = x - radius;
|
||||||
|
m_Box[BOXRIGHT] = x + radius;
|
||||||
|
m_Box[BOXBOTTOM] = y - radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearBox ()
|
||||||
|
{
|
||||||
|
m_Box[BOXTOP] = m_Box[BOXRIGHT] = FIXED_MIN;
|
||||||
|
m_Box[BOXBOTTOM] = m_Box[BOXLEFT] = FIXED_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
void ClearBox ();
|
|
||||||
void AddToBox (fixed_t x, fixed_t y);
|
void AddToBox (fixed_t x, fixed_t y);
|
||||||
|
|
||||||
inline fixed_t Top () { return m_Box[BOXTOP]; }
|
inline fixed_t Top () const { return m_Box[BOXTOP]; }
|
||||||
inline fixed_t Bottom () { return m_Box[BOXBOTTOM]; }
|
inline fixed_t Bottom () const { return m_Box[BOXBOTTOM]; }
|
||||||
inline fixed_t Left () { return m_Box[BOXLEFT]; }
|
inline fixed_t Left () const { return m_Box[BOXLEFT]; }
|
||||||
inline fixed_t Right () { return m_Box[BOXRIGHT]; }
|
inline fixed_t Right () const { return m_Box[BOXRIGHT]; }
|
||||||
|
|
||||||
|
int BoxOnLineSide (const line_t *ld) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
fixed_t m_Box[4];
|
fixed_t m_Box[4];
|
||||||
|
|
108
src/p_enemy.cpp
108
src/p_enemy.cpp
|
@ -32,6 +32,7 @@
|
||||||
#include "i_system.h"
|
#include "i_system.h"
|
||||||
#include "doomdef.h"
|
#include "doomdef.h"
|
||||||
#include "p_local.h"
|
#include "p_local.h"
|
||||||
|
#include "m_bbox.h"
|
||||||
#include "p_lnspec.h"
|
#include "p_lnspec.h"
|
||||||
#include "p_effect.h"
|
#include "p_effect.h"
|
||||||
#include "s_sound.h"
|
#include "s_sound.h"
|
||||||
|
@ -603,7 +604,9 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
|
||||||
}
|
}
|
||||||
|
|
||||||
// try other directions
|
// try other directions
|
||||||
if (pr_newchasedir() > 200 || abs(deltay) > abs(deltax))
|
if (!(actor->flags5 & MF5_AVOIDINGDROPOFF))
|
||||||
|
{
|
||||||
|
if ((pr_newchasedir() > 200 || abs(deltay) > abs(deltax)))
|
||||||
{
|
{
|
||||||
swap (d[1], d[2]);
|
swap (d[1], d[2]);
|
||||||
}
|
}
|
||||||
|
@ -612,6 +615,7 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
|
||||||
d[1] = DI_NODIR;
|
d[1] = DI_NODIR;
|
||||||
if (d[2] == turnaround)
|
if (d[2] == turnaround)
|
||||||
d[2] = DI_NODIR;
|
d[2] = DI_NODIR;
|
||||||
|
}
|
||||||
|
|
||||||
if (d[1] != DI_NODIR)
|
if (d[1] != DI_NODIR)
|
||||||
{
|
{
|
||||||
|
@ -630,6 +634,8 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(actor->flags5 & MF5_AVOIDINGDROPOFF))
|
||||||
|
{
|
||||||
// there is no direct path to the player, so pick another direction.
|
// there is no direct path to the player, so pick another direction.
|
||||||
if (olddir != DI_NODIR)
|
if (olddir != DI_NODIR)
|
||||||
{
|
{
|
||||||
|
@ -637,6 +643,7 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
|
||||||
if (P_TryWalk (actor))
|
if (P_TryWalk (actor))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// randomly determine direction of search
|
// randomly determine direction of search
|
||||||
if (pr_newchasedir() & 1)
|
if (pr_newchasedir() & 1)
|
||||||
|
@ -688,51 +695,6 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
|
||||||
// hang over dropoffs.
|
// hang over dropoffs.
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
|
|
||||||
struct avoiddropoff_t
|
|
||||||
{
|
|
||||||
AActor * thing;
|
|
||||||
fixed_t deltax;
|
|
||||||
fixed_t deltay;
|
|
||||||
fixed_t floorx;
|
|
||||||
fixed_t floory;
|
|
||||||
fixed_t floorz;
|
|
||||||
fixed_t t_bbox[4];
|
|
||||||
} a;
|
|
||||||
|
|
||||||
static bool PIT_AvoidDropoff(line_t *line)
|
|
||||||
{
|
|
||||||
if (line->backsector && // Ignore one-sided linedefs
|
|
||||||
a.t_bbox[BOXRIGHT] > line->bbox[BOXLEFT] &&
|
|
||||||
a.t_bbox[BOXLEFT] < line->bbox[BOXRIGHT] &&
|
|
||||||
a.t_bbox[BOXTOP] > line->bbox[BOXBOTTOM] && // Linedef must be contacted
|
|
||||||
a.t_bbox[BOXBOTTOM] < line->bbox[BOXTOP] &&
|
|
||||||
P_BoxOnLineSide(a.t_bbox, line) == -1)
|
|
||||||
{
|
|
||||||
fixed_t front = line->frontsector->floorplane.ZatPoint(a.floorx,a.floory);
|
|
||||||
fixed_t back = line->backsector->floorplane.ZatPoint(a.floorx,a.floory);
|
|
||||||
angle_t angle;
|
|
||||||
|
|
||||||
// The monster must contact one of the two floors,
|
|
||||||
// and the other must be a tall dropoff.
|
|
||||||
|
|
||||||
if (back == a.floorz && front < a.floorz - a.thing->MaxDropOffHeight)
|
|
||||||
{
|
|
||||||
angle = R_PointToAngle2(0,0,line->dx,line->dy); // front side dropoff
|
|
||||||
}
|
|
||||||
else if (front == a.floorz && back < a.floorz - a.thing->MaxDropOffHeight)
|
|
||||||
{
|
|
||||||
angle = R_PointToAngle2(line->dx,line->dy,0,0); // back side dropoff
|
|
||||||
}
|
|
||||||
else return true;
|
|
||||||
|
|
||||||
// Move away from dropoff at a standard speed.
|
|
||||||
// Multiple contacted linedefs are cumulative (e.g. hanging over corner)
|
|
||||||
a.deltax -= finesine[angle >> ANGLETOFINESHIFT]*32;
|
|
||||||
a.deltay += finecosine[angle >> ANGLETOFINESHIFT]*32;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
//
|
//
|
||||||
// P_NewChaseDir
|
// P_NewChaseDir
|
||||||
|
@ -777,26 +739,46 @@ void P_NewChaseDir(AActor * actor)
|
||||||
!(actor->flags2 & MF2_ONMOBJ) &&
|
!(actor->flags2 & MF2_ONMOBJ) &&
|
||||||
!(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF))
|
!(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF))
|
||||||
{
|
{
|
||||||
a.thing = actor;
|
FBoundingBox box(actor->x, actor->y, actor->radius);
|
||||||
a.deltax = a.deltay = 0;
|
FBlockLinesIterator it(box);
|
||||||
a.floorx = actor->x;
|
line_t *line;
|
||||||
a.floory = actor->y;
|
|
||||||
a.floorz = actor->z;
|
|
||||||
|
|
||||||
int yh=((a.t_bbox[BOXTOP] = actor->y+actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
|
fixed_t deltax = 0;
|
||||||
int yl=((a.t_bbox[BOXBOTTOM]= actor->y-actor->radius)-bmaporgy)>>MAPBLOCKSHIFT;
|
fixed_t deltay = 0;
|
||||||
int xh=((a.t_bbox[BOXRIGHT] = actor->x+actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
|
while ((line = it.Next()))
|
||||||
int xl=((a.t_bbox[BOXLEFT] = actor->x-actor->radius)-bmaporgx)>>MAPBLOCKSHIFT;
|
{
|
||||||
int bx, by;
|
if (line->backsector && // Ignore one-sided linedefs
|
||||||
|
box.Right() > line->bbox[BOXLEFT] &&
|
||||||
|
box.Left() < line->bbox[BOXRIGHT] &&
|
||||||
|
box.Top() > line->bbox[BOXBOTTOM] && // Linedef must be contacted
|
||||||
|
box.Bottom() < line->bbox[BOXTOP] &&
|
||||||
|
box.BoxOnLineSide(line) == -1)
|
||||||
|
{
|
||||||
|
fixed_t front = line->frontsector->floorplane.ZatPoint(actor->x,actor->y);
|
||||||
|
fixed_t back = line->backsector->floorplane.ZatPoint(actor->x,actor->y);
|
||||||
|
angle_t angle;
|
||||||
|
|
||||||
// check lines
|
// The monster must contact one of the two floors,
|
||||||
|
// and the other must be a tall dropoff.
|
||||||
|
|
||||||
validcount++;
|
if (back == actor->z && front < actor->z - actor->MaxDropOffHeight)
|
||||||
for (bx=xl ; bx<=xh ; bx++)
|
{
|
||||||
for (by=yl ; by<=yh ; by++)
|
angle = R_PointToAngle2(0,0,line->dx,line->dy); // front side dropoff
|
||||||
P_BlockLinesIterator(bx, by, PIT_AvoidDropoff); // all contacted lines
|
}
|
||||||
|
else if (front == actor->z && back < actor->z - actor->MaxDropOffHeight)
|
||||||
|
{
|
||||||
|
angle = R_PointToAngle2(line->dx,line->dy,0,0); // back side dropoff
|
||||||
|
}
|
||||||
|
else continue;
|
||||||
|
|
||||||
if (a.deltax || a.deltay)
|
// Move away from dropoff at a standard speed.
|
||||||
|
// Multiple contacted linedefs are cumulative (e.g. hanging over corner)
|
||||||
|
deltax -= finesine[angle >> ANGLETOFINESHIFT]*32;
|
||||||
|
deltay += finecosine[angle >> ANGLETOFINESHIFT]*32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deltax || deltay)
|
||||||
{
|
{
|
||||||
// [Graf Zahl] I have changed P_TryMove to only apply this logic when
|
// [Graf Zahl] I have changed P_TryMove to only apply this logic when
|
||||||
// being called from here. AVOIDINGDROPOFF activates the code that
|
// being called from here. AVOIDINGDROPOFF activates the code that
|
||||||
|
@ -806,7 +788,7 @@ void P_NewChaseDir(AActor * actor)
|
||||||
|
|
||||||
// use different dropoff movement logic in P_TryMove
|
// use different dropoff movement logic in P_TryMove
|
||||||
actor->flags5|=MF5_AVOIDINGDROPOFF;
|
actor->flags5|=MF5_AVOIDINGDROPOFF;
|
||||||
P_DoNewChaseDir(actor, a.deltax, a.deltay);
|
P_DoNewChaseDir(actor, deltax, deltay);
|
||||||
actor->flags5&=~MF5_AVOIDINGDROPOFF;
|
actor->flags5&=~MF5_AVOIDINGDROPOFF;
|
||||||
|
|
||||||
// If moving away from dropoff, set movecount to 1 so that
|
// If moving away from dropoff, set movecount to 1 so that
|
||||||
|
|
|
@ -234,7 +234,27 @@ struct FLineOpening
|
||||||
|
|
||||||
void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0);
|
void P_LineOpening (FLineOpening &open, AActor *thing, const line_t *linedef, fixed_t x, fixed_t y, fixed_t refx=FIXED_MIN, fixed_t refy=0);
|
||||||
|
|
||||||
bool P_BlockLinesIterator (int x, int y, bool(*func)(line_t*));
|
class FBoundingBox;
|
||||||
|
|
||||||
|
class FBlockLinesIterator
|
||||||
|
{
|
||||||
|
int minx, maxx;
|
||||||
|
int miny, maxy;
|
||||||
|
|
||||||
|
int curx, cury;
|
||||||
|
polyblock_t *polyLink;
|
||||||
|
int polyIndex;
|
||||||
|
int *list;
|
||||||
|
|
||||||
|
void StartBlock(int x, int y);
|
||||||
|
|
||||||
|
public:
|
||||||
|
FBlockLinesIterator(int minx, int miny, int maxx, int maxy, bool keepvalidcount = false);
|
||||||
|
FBlockLinesIterator(const FBoundingBox &box);
|
||||||
|
line_t *Next();
|
||||||
|
void Reset() { StartBlock(minx, miny); }
|
||||||
|
};
|
||||||
|
|
||||||
bool P_BlockThingsIterator (int x, int y, bool(*func)(AActor*), TArray<AActor *> &checkarray, AActor *start=NULL);
|
bool P_BlockThingsIterator (int x, int y, bool(*func)(AActor*), TArray<AActor *> &checkarray, AActor *start=NULL);
|
||||||
|
|
||||||
|
|
||||||
|
|
288
src/p_map.cpp
288
src/p_map.cpp
|
@ -100,8 +100,6 @@ int tmceilingpic;
|
||||||
sector_t *tmceilingsector;
|
sector_t *tmceilingsector;
|
||||||
bool tmtouchmidtex;
|
bool tmtouchmidtex;
|
||||||
|
|
||||||
static fixed_t tmfbbox[4];
|
|
||||||
static AActor *tmfthing;
|
|
||||||
fixed_t tmffloorz;
|
fixed_t tmffloorz;
|
||||||
fixed_t tmfceilingz;
|
fixed_t tmfceilingz;
|
||||||
fixed_t tmfdropoffz;
|
fixed_t tmfdropoffz;
|
||||||
|
@ -142,15 +140,15 @@ AActor *LastRipped;
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
static bool PIT_FindFloorCeiling (line_t *ld)
|
static bool PIT_FindFloorCeiling (line_t *ld, AActor *tmfthing, const FBoundingBox &box, fixed_t tmx, fixed_t tmy)
|
||||||
{
|
{
|
||||||
if (tmfbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|
if (box.Right() <= ld->bbox[BOXLEFT]
|
||||||
|| tmfbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|
|| box.Left() >= ld->bbox[BOXRIGHT]
|
||||||
|| tmfbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|
|| box.Top() <= ld->bbox[BOXBOTTOM]
|
||||||
|| tmfbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
|
|| box.Bottom() >= ld->bbox[BOXTOP] )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (P_BoxOnLineSide (tmfbbox, ld) != -1)
|
if (box.BoxOnLineSide (ld) != -1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// A line has been hit
|
// A line has been hit
|
||||||
|
@ -223,17 +221,13 @@ static bool PIT_FindFloorCeiling (line_t *ld)
|
||||||
|
|
||||||
void P_FindFloorCeiling (AActor *actor)
|
void P_FindFloorCeiling (AActor *actor)
|
||||||
{
|
{
|
||||||
int xl,xh,yl,yh,bx,by;
|
|
||||||
fixed_t x, y;
|
fixed_t x, y;
|
||||||
sector_t *sec;
|
sector_t *sec;
|
||||||
|
|
||||||
x = actor->x;
|
x = actor->x;
|
||||||
y = actor->y;
|
y = actor->y;
|
||||||
|
|
||||||
tmfbbox[BOXTOP] = y + actor->radius;
|
FBoundingBox box(x, y, actor->radius);
|
||||||
tmfbbox[BOXBOTTOM] = y - actor->radius;
|
|
||||||
tmfbbox[BOXRIGHT] = x + actor->radius;
|
|
||||||
tmfbbox[BOXLEFT] = x - actor->radius;
|
|
||||||
|
|
||||||
sec = P_PointInSector (x, y);
|
sec = P_PointInSector (x, y);
|
||||||
tmffloorz = tmfdropoffz = sec->floorplane.ZatPoint (x, y);
|
tmffloorz = tmfdropoffz = sec->floorplane.ZatPoint (x, y);
|
||||||
|
@ -242,18 +236,15 @@ void P_FindFloorCeiling (AActor *actor)
|
||||||
tmffloorsector = sec;
|
tmffloorsector = sec;
|
||||||
tmfceilingpic = sec->ceilingpic;
|
tmfceilingpic = sec->ceilingpic;
|
||||||
tmfceilingsector = sec;
|
tmfceilingsector = sec;
|
||||||
tmfthing = actor;
|
|
||||||
validcount++;
|
validcount++;
|
||||||
|
|
||||||
xl = (tmfbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT;
|
FBlockLinesIterator it(box);
|
||||||
xh = (tmfbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT;
|
line_t *ld;
|
||||||
yl = (tmfbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT;
|
|
||||||
yh = (tmfbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT;
|
|
||||||
|
|
||||||
for (bx = xl; bx <= xh; bx++)
|
while ((ld = it.Next()))
|
||||||
for (by = yl; by <= yh; by++)
|
{
|
||||||
if (!P_BlockLinesIterator (bx, by, PIT_FindFloorCeiling))
|
PIT_FindFloorCeiling(ld, actor, box, x, y);
|
||||||
return;
|
}
|
||||||
|
|
||||||
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
|
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
|
||||||
}
|
}
|
||||||
|
@ -340,10 +331,10 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
|
||||||
tmy = y;
|
tmy = y;
|
||||||
tmz = z;
|
tmz = z;
|
||||||
|
|
||||||
tmfbbox[BOXTOP] = tmbbox[BOXTOP] = y + tmthing->radius;
|
tmbbox[BOXTOP] = y + tmthing->radius;
|
||||||
tmfbbox[BOXBOTTOM] = tmbbox[BOXBOTTOM] = y - tmthing->radius;
|
tmbbox[BOXBOTTOM] = y - tmthing->radius;
|
||||||
tmfbbox[BOXRIGHT] = tmbbox[BOXRIGHT] = x + tmthing->radius;
|
tmbbox[BOXRIGHT] = x + tmthing->radius;
|
||||||
tmfbbox[BOXLEFT] = tmbbox[BOXLEFT] = x - tmthing->radius;
|
tmbbox[BOXLEFT] = x - tmthing->radius;
|
||||||
|
|
||||||
newsec = P_PointInSector (x,y);
|
newsec = P_PointInSector (x,y);
|
||||||
ceilingline = NULL;
|
ceilingline = NULL;
|
||||||
|
@ -356,7 +347,6 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
|
||||||
tmffloorsector = newsec;
|
tmffloorsector = newsec;
|
||||||
tmfceilingpic = newsec->ceilingpic;
|
tmfceilingpic = newsec->ceilingpic;
|
||||||
tmfceilingsector = newsec;
|
tmfceilingsector = newsec;
|
||||||
tmfthing = tmthing;
|
|
||||||
|
|
||||||
validcount++;
|
validcount++;
|
||||||
spechit.Clear ();
|
spechit.Clear ();
|
||||||
|
@ -364,21 +354,13 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
|
||||||
|
|
||||||
StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag;
|
StompAlwaysFrags = tmthing->player || (level.flags & LEVEL_MONSTERSTELEFRAG) || telefrag;
|
||||||
|
|
||||||
// stomp on any things contacted
|
FBoundingBox box(x, y, thing->radius);
|
||||||
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
FBlockLinesIterator it(box);
|
||||||
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
line_t *ld;
|
||||||
yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
|
||||||
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
|
||||||
|
|
||||||
for (bx=xl ; bx<=xh ; bx++)
|
while ((ld = it.Next()))
|
||||||
{
|
{
|
||||||
for (by=yl ; by<=yh ; by++)
|
PIT_FindFloorCeiling(ld, thing, box, x, y);
|
||||||
{
|
|
||||||
if (!P_BlockLinesIterator(bx,by,PIT_FindFloorCeiling))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
|
if (tmftouchmidtex) tmfdropoffz = tmffloorz;
|
||||||
|
@ -391,6 +373,13 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr
|
||||||
int savecpic = tmffloorpic;
|
int savecpic = tmffloorpic;
|
||||||
fixed_t savedropoff = tmfdropoffz;
|
fixed_t savedropoff = tmfdropoffz;
|
||||||
|
|
||||||
|
// stomp on any things contacted
|
||||||
|
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||||
|
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||||
|
yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||||
|
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||||
|
|
||||||
|
// stomp on any things contacted
|
||||||
for (bx=xl ; bx<=xh ; bx++)
|
for (bx=xl ; bx<=xh ; bx++)
|
||||||
{
|
{
|
||||||
for (by=yl ; by<=yh ; by++)
|
for (by=yl ; by<=yh ; by++)
|
||||||
|
@ -609,54 +598,23 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp)
|
||||||
// MOVEMENT ITERATOR FUNCTIONS
|
// MOVEMENT ITERATOR FUNCTIONS
|
||||||
//
|
//
|
||||||
|
|
||||||
// // phares
|
|
||||||
// PIT_CrossLine // |
|
|
||||||
// Checks to see if a PE->LS trajectory line crosses a blocking // V
|
|
||||||
// line. Returns false if it does.
|
|
||||||
//
|
|
||||||
// tmbbox holds the bounding box of the trajectory. If that box
|
|
||||||
// does not touch the bounding box of the line in question,
|
|
||||||
// then the trajectory is not blocked. If the PE is on one side
|
|
||||||
// of the line and the LS is on the other side, then the
|
|
||||||
// trajectory is blocked.
|
|
||||||
//
|
|
||||||
// Currently this assumes an infinite line, which is not quite
|
|
||||||
// correct. A more correct solution would be to check for an
|
|
||||||
// intersection of the trajectory and the line, but that takes
|
|
||||||
// longer and probably really isn't worth the effort.
|
|
||||||
//
|
|
||||||
|
|
||||||
static // killough 3/26/98: make static
|
|
||||||
bool PIT_CrossLine (line_t* ld)
|
|
||||||
{
|
|
||||||
if (!(ld->flags & ML_TWOSIDED) ||
|
|
||||||
(ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_BLOCKEVERYTHING)))
|
|
||||||
if (!(tmbbox[BOXLEFT] > ld->bbox[BOXRIGHT] ||
|
|
||||||
tmbbox[BOXRIGHT] < ld->bbox[BOXLEFT] ||
|
|
||||||
tmbbox[BOXTOP] < ld->bbox[BOXBOTTOM] ||
|
|
||||||
tmbbox[BOXBOTTOM] > ld->bbox[BOXTOP]))
|
|
||||||
if (P_PointOnLineSide(pe_x,pe_y,ld) != P_PointOnLineSide(ls_x,ls_y,ld))
|
|
||||||
return(false); // line blocks trajectory // ^
|
|
||||||
return(true); // line doesn't block trajectory // |
|
|
||||||
} // phares
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// PIT_CheckLine
|
// PIT_CheckLine
|
||||||
// Adjusts tmfloorz and tmceilingz as lines are contacted
|
// Adjusts tmfloorz and tmceilingz as lines are contacted
|
||||||
//
|
//
|
||||||
|
|
||||||
static // killough 3/26/98: make static
|
static // killough 3/26/98: make static
|
||||||
bool PIT_CheckLine (line_t *ld)
|
bool PIT_CheckLine (line_t *ld, const FBoundingBox &box)
|
||||||
{
|
{
|
||||||
bool rail = false;
|
bool rail = false;
|
||||||
|
|
||||||
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|
if (box.Right() <= ld->bbox[BOXLEFT]
|
||||||
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|
|| box.Left() >= ld->bbox[BOXRIGHT]
|
||||||
|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|
|| box.Top() <= ld->bbox[BOXBOTTOM]
|
||||||
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] )
|
|| box.Bottom() >= ld->bbox[BOXTOP] )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (P_BoxOnLineSide (tmbbox, ld) != -1)
|
if (box.BoxOnLineSide (ld) != -1)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// A line has been hit
|
// A line has been hit
|
||||||
|
@ -1113,51 +1071,6 @@ bool PIT_CheckThing (AActor *thing)
|
||||||
// return !(thing->flags & MF_SOLID); // old code -- killough
|
// return !(thing->flags & MF_SOLID); // old code -- killough
|
||||||
}
|
}
|
||||||
|
|
||||||
// This routine checks for Lost Souls trying to be spawned // phares
|
|
||||||
// across 1-sided lines, impassible lines, or "monsters can't // |
|
|
||||||
// cross" lines. Draw an imaginary line between the PE // V
|
|
||||||
// and the new Lost Soul spawn spot. If that line crosses
|
|
||||||
// a 'blocking' line, then disallow the spawn. Only search
|
|
||||||
// lines in the blocks of the blockmap where the bounding box
|
|
||||||
// of the trajectory line resides. Then check bounding box
|
|
||||||
// of the trajectory vs. the bounding box of each blocking
|
|
||||||
// line to see if the trajectory and the blocking line cross.
|
|
||||||
// Then check the PE and LS to see if they're on different
|
|
||||||
// sides of the blocking line. If so, return true, otherwise
|
|
||||||
// false.
|
|
||||||
|
|
||||||
bool Check_Sides(AActor* actor, int x, int y)
|
|
||||||
{
|
|
||||||
int bx,by,xl,xh,yl,yh;
|
|
||||||
|
|
||||||
pe_x = actor->x;
|
|
||||||
pe_y = actor->y;
|
|
||||||
ls_x = x;
|
|
||||||
ls_y = y;
|
|
||||||
|
|
||||||
// Here is the bounding box of the trajectory
|
|
||||||
|
|
||||||
tmbbox[BOXLEFT] = pe_x < x ? pe_x : x;
|
|
||||||
tmbbox[BOXRIGHT] = pe_x > x ? pe_x : x;
|
|
||||||
tmbbox[BOXTOP] = pe_y > y ? pe_y : y;
|
|
||||||
tmbbox[BOXBOTTOM] = pe_y < y ? pe_y : y;
|
|
||||||
|
|
||||||
// Determine which blocks to look in for blocking lines
|
|
||||||
|
|
||||||
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
|
|
||||||
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
|
|
||||||
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
|
|
||||||
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
|
|
||||||
|
|
||||||
// xl->xh, yl->yh determine the mapblock set to search
|
|
||||||
|
|
||||||
validcount++; // prevents checking same line twice
|
|
||||||
for (bx = xl ; bx <= xh ; bx++)
|
|
||||||
for (by = yl ; by <= yh ; by++)
|
|
||||||
if (!P_BlockLinesIterator(bx,by,PIT_CrossLine))
|
|
||||||
return true; // ^
|
|
||||||
return(false); // |
|
|
||||||
} // phares
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
//
|
//
|
||||||
|
@ -1286,10 +1199,12 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
|
||||||
tmx = x;
|
tmx = x;
|
||||||
tmy = y;
|
tmy = y;
|
||||||
|
|
||||||
tmbbox[BOXTOP] = y + thing->radius;
|
FBoundingBox box(x, y, thing->radius);
|
||||||
tmbbox[BOXBOTTOM] = y - thing->radius;
|
|
||||||
tmbbox[BOXRIGHT] = x + thing->radius;
|
tmbbox[BOXTOP] = box.Top();
|
||||||
tmbbox[BOXLEFT] = x - thing->radius;
|
tmbbox[BOXBOTTOM] = box.Bottom();
|
||||||
|
tmbbox[BOXRIGHT] = box.Right();
|
||||||
|
tmbbox[BOXLEFT] = box.Left();
|
||||||
|
|
||||||
newsec = P_PointInSector (x,y);
|
newsec = P_PointInSector (x,y);
|
||||||
ceilingline = BlockingLine = NULL;
|
ceilingline = BlockingLine = NULL;
|
||||||
|
@ -1407,19 +1322,18 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y)
|
||||||
thing->height = realheight;
|
thing->height = realheight;
|
||||||
if (tmflags & MF_NOCLIP)
|
if (tmflags & MF_NOCLIP)
|
||||||
return (BlockingMobj = thingblocker) == NULL;
|
return (BlockingMobj = thingblocker) == NULL;
|
||||||
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
|
|
||||||
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
|
FBlockLinesIterator it(box);
|
||||||
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
|
line_t *ld;
|
||||||
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
|
|
||||||
|
|
||||||
fixed_t thingdropoffz = tmfloorz;
|
fixed_t thingdropoffz = tmfloorz;
|
||||||
//bool onthing = (thingdropoffz != tmdropoffz);
|
//bool onthing = (thingdropoffz != tmdropoffz);
|
||||||
tmfloorz = tmdropoffz;
|
tmfloorz = tmdropoffz;
|
||||||
|
|
||||||
for (bx=xl ; bx<=xh ; bx++)
|
while ((ld = it.Next()))
|
||||||
for (by=yl ; by<=yh ; by++)
|
{
|
||||||
if (!P_BlockLinesIterator (bx,by,PIT_CheckLine))
|
if (!PIT_CheckLine(ld, box)) return false;
|
||||||
return false;
|
}
|
||||||
|
|
||||||
if (tmceilingz - tmfloorz < thing->height)
|
if (tmceilingz - tmfloorz < thing->height)
|
||||||
return false;
|
return false;
|
||||||
|
@ -4713,50 +4627,6 @@ void P_DelSeclist (msecnode_t *node)
|
||||||
node = P_DelSecnode (node);
|
node = P_DelSecnode (node);
|
||||||
}
|
}
|
||||||
|
|
||||||
//=============================================================================
|
|
||||||
// phares 3/14/98
|
|
||||||
//
|
|
||||||
// PIT_GetSectors
|
|
||||||
//
|
|
||||||
// Locates all the sectors the object is in by looking at the lines that
|
|
||||||
// cross through it. You have already decided that the object is allowed
|
|
||||||
// at this location, so don't bother with checking impassable or
|
|
||||||
// blocking lines.
|
|
||||||
//=============================================================================
|
|
||||||
|
|
||||||
bool PIT_GetSectors (line_t *ld)
|
|
||||||
{
|
|
||||||
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] ||
|
|
||||||
tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] ||
|
|
||||||
tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] ||
|
|
||||||
tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (P_BoxOnLineSide (tmbbox, ld) != -1)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// This line crosses through the object.
|
|
||||||
|
|
||||||
// Collect the sector(s) from the line and add to the
|
|
||||||
// sector_list you're examining. If the Thing ends up being
|
|
||||||
// allowed to move to this position, then the sector_list
|
|
||||||
// will be attached to the Thing's AActor at touching_sectorlist.
|
|
||||||
|
|
||||||
sector_list = P_AddSecnode (ld->frontsector,tmthing,sector_list);
|
|
||||||
|
|
||||||
// Don't assume all lines are 2-sided, since some Things
|
|
||||||
// like MT_TFOG are allowed regardless of whether their radius takes
|
|
||||||
// them beyond an impassable linedef.
|
|
||||||
|
|
||||||
// killough 3/27/98, 4/4/98:
|
|
||||||
// Use sidedefs instead of 2s flag to determine two-sidedness.
|
|
||||||
|
|
||||||
if (ld->backsector)
|
|
||||||
sector_list = P_AddSecnode(ld->backsector, tmthing, sector_list);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
// phares 3/14/98
|
// phares 3/14/98
|
||||||
//
|
//
|
||||||
|
@ -4768,18 +4638,8 @@ bool PIT_GetSectors (line_t *ld)
|
||||||
|
|
||||||
void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
|
void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
|
||||||
{
|
{
|
||||||
int xl, xh, yl, yh, bx, by;
|
|
||||||
msecnode_t *node;
|
msecnode_t *node;
|
||||||
|
|
||||||
// [RH] Save old tm* values.
|
|
||||||
AActor *thingsave = tmthing;
|
|
||||||
int flagssave = tmflags;
|
|
||||||
fixed_t xsave = tmx;
|
|
||||||
fixed_t ysave = tmy;
|
|
||||||
fixed_t bboxsave[4];
|
|
||||||
|
|
||||||
memcpy (bboxsave, tmbbox, sizeof(bboxsave));
|
|
||||||
|
|
||||||
// First, clear out the existing m_thing fields. As each node is
|
// First, clear out the existing m_thing fields. As each node is
|
||||||
// added or verified as needed, m_thing will be set properly. When
|
// added or verified as needed, m_thing will be set properly. When
|
||||||
// finished, delete all nodes where m_thing is still NULL. These
|
// finished, delete all nodes where m_thing is still NULL. These
|
||||||
|
@ -4792,27 +4652,40 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
|
||||||
node = node->m_tnext;
|
node = node->m_tnext;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmthing = thing;
|
FBoundingBox box(thing->x, thing->y, thing->radius);
|
||||||
tmflags = thing->flags;
|
FBlockLinesIterator it(box);
|
||||||
|
line_t *ld;
|
||||||
|
|
||||||
tmx = x;
|
while ((ld = it.Next()))
|
||||||
tmy = y;
|
{
|
||||||
|
if (box.Right() <= ld->bbox[BOXLEFT] ||
|
||||||
|
box.Left() >= ld->bbox[BOXRIGHT] ||
|
||||||
|
box.Top() <= ld->bbox[BOXBOTTOM] ||
|
||||||
|
box.Bottom() >= ld->bbox[BOXTOP])
|
||||||
|
continue;
|
||||||
|
|
||||||
tmbbox[BOXTOP] = y + tmthing->radius;
|
if (box.BoxOnLineSide (ld) != -1)
|
||||||
tmbbox[BOXBOTTOM] = y - tmthing->radius;
|
continue;
|
||||||
tmbbox[BOXRIGHT] = x + tmthing->radius;
|
|
||||||
tmbbox[BOXLEFT] = x - tmthing->radius;
|
|
||||||
|
|
||||||
validcount++; // used to make sure we only process a line once
|
// This line crosses through the object.
|
||||||
|
|
||||||
xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT;
|
// Collect the sector(s) from the line and add to the
|
||||||
xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT;
|
// sector_list you're examining. If the Thing ends up being
|
||||||
yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT;
|
// allowed to move to this position, then the sector_list
|
||||||
yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT;
|
// will be attached to the Thing's AActor at touching_sectorlist.
|
||||||
|
|
||||||
for (bx = xl; bx <= xh; bx++)
|
sector_list = P_AddSecnode (ld->frontsector,thing,sector_list);
|
||||||
for (by = yl; by <= yh; by++)
|
|
||||||
P_BlockLinesIterator (bx,by,PIT_GetSectors);
|
// Don't assume all lines are 2-sided, since some Things
|
||||||
|
// like MT_TFOG are allowed regardless of whether their radius takes
|
||||||
|
// them beyond an impassable linedef.
|
||||||
|
|
||||||
|
// killough 3/27/98, 4/4/98:
|
||||||
|
// Use sidedefs instead of 2s flag to determine two-sidedness.
|
||||||
|
|
||||||
|
if (ld->backsector)
|
||||||
|
sector_list = P_AddSecnode(ld->backsector, thing, sector_list);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the sector of the (x,y) point to sector_list.
|
// Add the sector of the (x,y) point to sector_list.
|
||||||
|
|
||||||
|
@ -4835,13 +4708,6 @@ void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y)
|
||||||
node = node->m_tnext;
|
node = node->m_tnext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// [RH] Restore old tm* values.
|
|
||||||
tmthing = thingsave;
|
|
||||||
tmflags = flagssave;
|
|
||||||
tmx = xsave;
|
|
||||||
tmy = ysave;
|
|
||||||
memcpy (tmbbox, bboxsave, sizeof(bboxsave));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
|
void SpawnShootDecal (AActor *t1, const FTraceResults &trace)
|
||||||
|
|
169
src/p_maputl.cpp
169
src/p_maputl.cpp
|
@ -677,75 +677,119 @@ void FBlockNode::Release ()
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_BlockLinesIterator
|
// FBlockLinesIterator
|
||||||
// The validcount flags are used to avoid checking lines
|
|
||||||
// that are marked in multiple mapblocks,
|
|
||||||
// so increment validcount before the first call
|
|
||||||
// to P_BlockLinesIterator, then make one or more calls
|
|
||||||
// to it.
|
|
||||||
//
|
//
|
||||||
extern polyblock_t **PolyBlockMap;
|
extern polyblock_t **PolyBlockMap;
|
||||||
|
|
||||||
bool P_BlockLinesIterator (int x, int y, bool(*func)(line_t*))
|
FBlockLinesIterator::FBlockLinesIterator(int _minx, int _miny, int _maxx, int _maxy, bool keepvalidcount)
|
||||||
{
|
{
|
||||||
if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight)
|
if (!keepvalidcount) validcount++;
|
||||||
{
|
minx = _minx;
|
||||||
return true;
|
maxx = _maxx;
|
||||||
}
|
miny = _miny;
|
||||||
else
|
maxy = _maxy;
|
||||||
{
|
Reset();
|
||||||
int offset;
|
}
|
||||||
int *list;
|
|
||||||
|
|
||||||
/* [RH] Polyobj stuff from Hexen --> */
|
FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
|
||||||
polyblock_t *polyLink;
|
{
|
||||||
|
validcount++;
|
||||||
|
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||||
|
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||||
|
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||||
|
minx = (box.Left() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
offset = y*bmapwidth + x;
|
|
||||||
if (PolyBlockMap)
|
|
||||||
{
|
|
||||||
polyLink = PolyBlockMap[offset];
|
|
||||||
while (polyLink)
|
|
||||||
{
|
|
||||||
if (polyLink->polyobj && polyLink->polyobj->validcount != validcount)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
seg_t **tempSeg = polyLink->polyobj->segs;
|
|
||||||
polyLink->polyobj->validcount = validcount;
|
|
||||||
|
|
||||||
for (i = polyLink->polyobj->numsegs; i; i--, tempSeg++)
|
void FBlockLinesIterator::StartBlock(int x, int y)
|
||||||
|
{
|
||||||
|
if (x >= 0 && y >= 0 && x < bmapwidth && y <bmapheight)
|
||||||
{
|
{
|
||||||
if ((*tempSeg)->linedef->validcount != validcount)
|
curx = x;
|
||||||
{
|
cury = y;
|
||||||
(*tempSeg)->linedef->validcount = validcount;
|
int offset = y*bmapwidth + x;
|
||||||
if (!func ((*tempSeg)->linedef))
|
polyLink = PolyBlockMap? PolyBlockMap[offset] : NULL;
|
||||||
return false;
|
polyIndex = 0;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
polyLink = polyLink->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* <-- Polyobj stuff from Hexen */
|
|
||||||
|
|
||||||
offset = *(blockmap + offset);
|
|
||||||
|
|
||||||
// There is an extra entry at the beginning of every block.
|
// There is an extra entry at the beginning of every block.
|
||||||
// Apparently, id had originally intended for it to be used
|
// Apparently, id had originally intended for it to be used
|
||||||
// to keep track of things, but the final code does not do that.
|
// to keep track of things, but the final code does not do that.
|
||||||
for (list = blockmaplump + offset + 1; *list != -1; list++)
|
list = blockmaplump + *(blockmap + offset) + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// invalid block
|
||||||
|
list = NULL;
|
||||||
|
polyLink = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
line_t *FBlockLinesIterator::Next()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
while (polyLink != NULL)
|
||||||
|
{
|
||||||
|
if (polyLink->polyobj)
|
||||||
|
{
|
||||||
|
if (polyIndex == 0)
|
||||||
|
{
|
||||||
|
if (polyLink->polyobj->validcount == validcount)
|
||||||
|
{
|
||||||
|
polyLink = polyLink->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
polyLink->polyobj->validcount = validcount;
|
||||||
|
}
|
||||||
|
|
||||||
|
seg_t *seg = polyLink->polyobj->segs[polyIndex];
|
||||||
|
|
||||||
|
if (++polyIndex >= polyLink->polyobj->numsegs)
|
||||||
|
{
|
||||||
|
polyLink = polyLink->next;
|
||||||
|
polyIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
line_t *ld = seg->linedef;
|
||||||
|
if (ld->validcount == validcount)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ld->validcount = validcount;
|
||||||
|
return ld;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else polyLink = polyLink->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list != NULL)
|
||||||
|
{
|
||||||
|
while (*list != -1)
|
||||||
{
|
{
|
||||||
line_t *ld = &lines[*list];
|
line_t *ld = &lines[*list];
|
||||||
|
|
||||||
if (ld->validcount != validcount)
|
if (ld->validcount != validcount)
|
||||||
{
|
{
|
||||||
ld->validcount = validcount;
|
ld->validcount = validcount;
|
||||||
|
return ld;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( !func(ld) )
|
if (++curx > maxx)
|
||||||
return false;
|
{
|
||||||
|
curx = minx;
|
||||||
|
if (++cury > maxy) return NULL;
|
||||||
}
|
}
|
||||||
|
StartBlock(curx, cury);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true; // everything was checked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -829,8 +873,13 @@ int ptflags;
|
||||||
// are on opposite sides of the trace.
|
// are on opposite sides of the trace.
|
||||||
// Returns true if earlyout and a solid line hit.
|
// Returns true if earlyout and a solid line hit.
|
||||||
//
|
//
|
||||||
bool PIT_AddLineIntercepts (line_t *ld)
|
void P_AddLineIntercepts(int bx, int by)
|
||||||
{
|
{
|
||||||
|
FBlockLinesIterator it(bx, by, bx, by, true);
|
||||||
|
line_t *ld;
|
||||||
|
|
||||||
|
while ((ld = it.Next()))
|
||||||
|
{
|
||||||
int s1;
|
int s1;
|
||||||
int s2;
|
int s2;
|
||||||
fixed_t frac;
|
fixed_t frac;
|
||||||
|
@ -851,16 +900,15 @@ bool PIT_AddLineIntercepts (line_t *ld)
|
||||||
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
|
s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s1 == s2)
|
if (s1 == s2) continue; // line isn't crossed
|
||||||
return true; // line isn't crossed
|
|
||||||
|
|
||||||
// hit the line
|
// hit the line
|
||||||
P_MakeDivline (ld, &dl);
|
P_MakeDivline (ld, &dl);
|
||||||
frac = P_InterceptVector (&trace, &dl);
|
frac = P_InterceptVector (&trace, &dl);
|
||||||
|
|
||||||
if (frac < 0)
|
if (frac < 0) continue; // behind source
|
||||||
return true; // behind source
|
|
||||||
|
|
||||||
|
/* unused code
|
||||||
// try to early out the check
|
// try to early out the check
|
||||||
if (earlyout
|
if (earlyout
|
||||||
&& frac < FRACUNIT
|
&& frac < FRACUNIT
|
||||||
|
@ -868,6 +916,7 @@ bool PIT_AddLineIntercepts (line_t *ld)
|
||||||
{
|
{
|
||||||
return false; // stop checking
|
return false; // stop checking
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
intercept_t newintercept;
|
intercept_t newintercept;
|
||||||
|
@ -876,12 +925,10 @@ bool PIT_AddLineIntercepts (line_t *ld)
|
||||||
newintercept.isaline = true;
|
newintercept.isaline = true;
|
||||||
newintercept.d.line = ld;
|
newintercept.d.line = ld;
|
||||||
intercepts.Push (newintercept);
|
intercepts.Push (newintercept);
|
||||||
|
}
|
||||||
return true; // continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// PIT_AddThingIntercepts
|
// PIT_AddThingIntercepts
|
||||||
//
|
//
|
||||||
|
@ -1145,8 +1192,7 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
||||||
{
|
{
|
||||||
if (flags & PT_ADDLINES)
|
if (flags & PT_ADDLINES)
|
||||||
{
|
{
|
||||||
if (!P_BlockLinesIterator (mapx, mapy, PIT_AddLineIntercepts))
|
P_AddLineIntercepts(mapx, mapy);
|
||||||
return false; // early out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PT_ADDTHINGS)
|
if (flags & PT_ADDTHINGS)
|
||||||
|
@ -1184,9 +1230,8 @@ 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)
|
||||||
{
|
{
|
||||||
if (!P_BlockLinesIterator (mapx + mapxstep, mapy, PIT_AddLineIntercepts) ||
|
P_AddLineIntercepts(mapx + mapxstep, mapy);
|
||||||
!P_BlockLinesIterator (mapx, mapy + mapystep, PIT_AddLineIntercepts))
|
P_AddLineIntercepts(mapx, mapy + mapystep);
|
||||||
return false; // early out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & PT_ADDTHINGS)
|
if (flags & PT_ADDTHINGS)
|
||||||
|
@ -1330,3 +1375,5 @@ static AActor *RoughBlockCheck (AActor *mo, int index)
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3642,6 +3642,7 @@ APlayerPawn *P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer)
|
||||||
p->damagecount = 0;
|
p->damagecount = 0;
|
||||||
p->bonuscount = 0;
|
p->bonuscount = 0;
|
||||||
p->morphTics = 0;
|
p->morphTics = 0;
|
||||||
|
p->MorphedPlayerClass = 0;
|
||||||
p->extralight = 0;
|
p->extralight = 0;
|
||||||
p->fixedcolormap = 0;
|
p->fixedcolormap = 0;
|
||||||
p->viewheight = mobj->ViewHeight;
|
p->viewheight = mobj->ViewHeight;
|
||||||
|
|
|
@ -242,6 +242,7 @@ player_s::player_s()
|
||||||
attacker(0),
|
attacker(0),
|
||||||
extralight(0),
|
extralight(0),
|
||||||
morphTics(0),
|
morphTics(0),
|
||||||
|
MorphedPlayerClass(0),
|
||||||
PremorphWeapon(0),
|
PremorphWeapon(0),
|
||||||
chickenPeck(0),
|
chickenPeck(0),
|
||||||
jumpTics(0),
|
jumpTics(0),
|
||||||
|
@ -2415,6 +2416,7 @@ void player_s::Serialize (FArchive &arc)
|
||||||
<< extralight
|
<< extralight
|
||||||
<< fixedcolormap
|
<< fixedcolormap
|
||||||
<< morphTics
|
<< morphTics
|
||||||
|
<< MorphedPlayerClass
|
||||||
<< PremorphWeapon
|
<< PremorphWeapon
|
||||||
<< chickenPeck
|
<< chickenPeck
|
||||||
<< jumpTics
|
<< jumpTics
|
||||||
|
|
|
@ -1068,7 +1068,6 @@ static bool CheckMobjBlocking (seg_t *seg, polyobj_t *po)
|
||||||
AActor *mobj;
|
AActor *mobj;
|
||||||
int i, j, k;
|
int i, j, k;
|
||||||
int left, right, top, bottom;
|
int left, right, top, bottom;
|
||||||
fixed_t tmbbox[4];
|
|
||||||
line_t *ld;
|
line_t *ld;
|
||||||
bool blocked;
|
bool blocked;
|
||||||
|
|
||||||
|
@ -1110,19 +1109,16 @@ static bool CheckMobjBlocking (seg_t *seg, polyobj_t *po)
|
||||||
checker.Push (mobj);
|
checker.Push (mobj);
|
||||||
if ((mobj->flags&MF_SOLID) && !(mobj->flags&MF_NOCLIP))
|
if ((mobj->flags&MF_SOLID) && !(mobj->flags&MF_NOCLIP))
|
||||||
{
|
{
|
||||||
tmbbox[BOXTOP] = mobj->y+mobj->radius;
|
FBoundingBox box(mobj->x, mobj->y, mobj->radius);
|
||||||
tmbbox[BOXBOTTOM] = mobj->y-mobj->radius;
|
|
||||||
tmbbox[BOXLEFT] = mobj->x-mobj->radius;
|
|
||||||
tmbbox[BOXRIGHT] = mobj->x+mobj->radius;
|
|
||||||
|
|
||||||
if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT]
|
if (box.Right() <= ld->bbox[BOXLEFT]
|
||||||
|| tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT]
|
|| box.Left() >= ld->bbox[BOXRIGHT]
|
||||||
|| tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM]
|
|| box.Top() <= ld->bbox[BOXBOTTOM]
|
||||||
|| tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP])
|
|| box.Bottom() >= ld->bbox[BOXTOP])
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (P_BoxOnLineSide(tmbbox, ld) != -1)
|
if (box.BoxOnLineSide(ld) != -1)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@
|
||||||
#define __V_VIDEO_H__
|
#define __V_VIDEO_H__
|
||||||
|
|
||||||
#include "doomtype.h"
|
#include "doomtype.h"
|
||||||
#include "m_bbox.h"
|
|
||||||
|
|
||||||
#include "v_palette.h"
|
#include "v_palette.h"
|
||||||
#include "v_font.h"
|
#include "v_font.h"
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
// SAVESIG should match SAVEVER.
|
// SAVESIG should match SAVEVER.
|
||||||
|
|
||||||
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
// MINSAVEVER is the minimum level snapshot version that can be loaded.
|
||||||
#define MINSAVEVER 879
|
#define MINSAVEVER 887
|
||||||
|
|
||||||
#if SVN_REVISION_NUMBER < MINSAVEVER
|
#if SVN_REVISION_NUMBER < MINSAVEVER
|
||||||
// Never write a savegame with a version lower than what we need
|
// Never write a savegame with a version lower than what we need
|
||||||
|
|
Loading…
Reference in a new issue