From ebd17de30a5223d1e34425261af367c5734e8ac7 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 6 Apr 2008 17:33:43 +0000 Subject: [PATCH] - 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) --- docs/rh-log.txt | 13 ++ src/doomtype.h | 11 + src/g_doom/a_painelemental.cpp | 22 +- src/g_heretic/a_hereticartifacts.cpp | 1 + src/g_shared/a_morph.cpp | 1 + src/m_bbox.cpp | 17 +- src/m_bbox.h | 49 +++-- src/p_enemy.cpp | 130 ++++++------ src/p_local.h | 22 +- src/p_map.cpp | 288 +++++++-------------------- src/p_maputl.cpp | 255 ++++++++++++++---------- src/p_mobj.cpp | 1 + src/p_user.cpp | 2 + src/po_man.cpp | 16 +- src/v_video.h | 1 - src/version.h | 2 +- 16 files changed, 400 insertions(+), 431 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 541b7cae86..b7013d8656 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,17 @@ 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 the time freezer powerup. - Changed: Empty pickup messages are no longer printed. diff --git a/src/doomtype.h b/src/doomtype.h index 1b689fd8f2..6b2946af43 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -124,6 +124,17 @@ typedef struct _GUID } GUID; #endif + +// Bounding box coordinate storage. +enum +{ + BOXTOP, + BOXBOTTOM, + BOXLEFT, + BOXRIGHT +}; // bbox coordinates + + // // Fixed point, 32bit as 16.16. // diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index 91a505c0ae..f84aca3682 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -4,6 +4,8 @@ #include "p_local.h" #include "a_doomglobal.h" #include "a_action.h" +#include "templates.h" +#include "m_bbox.h" #include "thingdef/thingdef.h" void A_PainAttack (AActor *); @@ -23,6 +25,7 @@ static const PClass *GetSpawnType() return spawntype; } + // // A_PainShootSkull // 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.// | // 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); diff --git a/src/g_heretic/a_hereticartifacts.cpp b/src/g_heretic/a_hereticartifacts.cpp index 4463ea01b6..c3e61d8ce9 100644 --- a/src/g_heretic/a_hereticartifacts.cpp +++ b/src/g_heretic/a_hereticartifacts.cpp @@ -41,6 +41,7 @@ bool AArtiTomeOfPower::Use (bool pickup) else { // Succeeded Owner->player->morphTics = 0; + Owner->player->MorphedPlayerClass = 0; S_Sound (Owner, CHAN_VOICE, "*evillaugh", 1, ATTN_IDLE); } return true; diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 7ae1e9e52a..e0812c7c9d 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -199,6 +199,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force) mo->flags3 = (mo->flags3 & ~MF3_GHOST) | (pmo->flags3 & MF3_GHOST); player->morphTics = 0; + player->MorphedPlayerClass = 0; player->viewheight = mo->ViewHeight; AInventory *level2 = mo->FindInventory (RUNTIME_CLASS(APowerWeaponLevel2)); if (level2 != NULL) diff --git a/src/m_bbox.cpp b/src/m_bbox.cpp index 7be4e90c89..3a938ab18c 100644 --- a/src/m_bbox.cpp +++ b/src/m_bbox.cpp @@ -25,17 +25,7 @@ //----------------------------------------------------------------------------- #include "m_bbox.h" - -FBoundingBox::FBoundingBox () -{ - ClearBox (); -} - -void FBoundingBox::ClearBox () -{ - m_Box[BOXTOP] = m_Box[BOXRIGHT] = FIXED_MIN; - m_Box[BOXBOTTOM] = m_Box[BOXLEFT] = FIXED_MAX; -} +#include "p_local.h" 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; } +int FBoundingBox::BoxOnLineSide (const line_t *ld) const +{ + return P_BoxOnLineSide(m_Box, ld); +} + diff --git a/src/m_bbox.h b/src/m_bbox.h index 7a813ffa1f..43683a58a1 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -25,29 +25,46 @@ #include "doomtype.h" #include "m_fixed.h" - -// Bounding box coordinate storage. -enum -{ - BOXTOP, - BOXBOTTOM, - BOXLEFT, - BOXRIGHT -}; // bbox coordinates - +struct line_t; class FBoundingBox { 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); - inline fixed_t Top () { return m_Box[BOXTOP]; } - inline fixed_t Bottom () { return m_Box[BOXBOTTOM]; } - inline fixed_t Left () { return m_Box[BOXLEFT]; } - inline fixed_t Right () { return m_Box[BOXRIGHT]; } + inline fixed_t Top () const { return m_Box[BOXTOP]; } + inline fixed_t Bottom () const { return m_Box[BOXBOTTOM]; } + inline fixed_t Left () const { return m_Box[BOXLEFT]; } + inline fixed_t Right () const { return m_Box[BOXRIGHT]; } + + int BoxOnLineSide (const line_t *ld) const; protected: fixed_t m_Box[4]; diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 44d5421519..c17abdf58b 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -32,6 +32,7 @@ #include "i_system.h" #include "doomdef.h" #include "p_local.h" +#include "m_bbox.h" #include "p_lnspec.h" #include "p_effect.h" #include "s_sound.h" @@ -603,15 +604,18 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay) } // try other directions - if (pr_newchasedir() > 200 || abs(deltay) > abs(deltax)) + if (!(actor->flags5 & MF5_AVOIDINGDROPOFF)) { - swap (d[1], d[2]); - } + if ((pr_newchasedir() > 200 || abs(deltay) > abs(deltax))) + { + swap (d[1], d[2]); + } - if (d[1] == turnaround) - d[1] = DI_NODIR; - if (d[2] == turnaround) - d[2] = DI_NODIR; + if (d[1] == turnaround) + d[1] = DI_NODIR; + if (d[2] == turnaround) + d[2] = DI_NODIR; + } if (d[1] != DI_NODIR) { @@ -630,12 +634,15 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay) return; } - // there is no direct path to the player, so pick another direction. - if (olddir != DI_NODIR) + if (!(actor->flags5 & MF5_AVOIDINGDROPOFF)) { - actor->movedir = olddir; - if (P_TryWalk (actor)) - return; + // there is no direct path to the player, so pick another direction. + if (olddir != DI_NODIR) + { + actor->movedir = olddir; + if (P_TryWalk (actor)) + return; + } } // randomly determine direction of search @@ -688,51 +695,6 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay) // 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 @@ -777,26 +739,46 @@ void P_NewChaseDir(AActor * actor) !(actor->flags2 & MF2_ONMOBJ) && !(actor->flags & MF_FLOAT) && !(i_compatflags & COMPATF_DROPOFF)) { - a.thing = actor; - a.deltax = a.deltay = 0; - a.floorx = actor->x; - a.floory = actor->y; - a.floorz = actor->z; + FBoundingBox box(actor->x, actor->y, actor->radius); + FBlockLinesIterator it(box); + line_t *line; - int yh=((a.t_bbox[BOXTOP] = actor->y+actor->radius)-bmaporgy)>>MAPBLOCKSHIFT; - int yl=((a.t_bbox[BOXBOTTOM]= actor->y-actor->radius)-bmaporgy)>>MAPBLOCKSHIFT; - int xh=((a.t_bbox[BOXRIGHT] = actor->x+actor->radius)-bmaporgx)>>MAPBLOCKSHIFT; - int xl=((a.t_bbox[BOXLEFT] = actor->x-actor->radius)-bmaporgx)>>MAPBLOCKSHIFT; - int bx, by; + fixed_t deltax = 0; + fixed_t deltay = 0; + while ((line = it.Next())) + { + 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. + + if (back == actor->z && front < actor->z - actor->MaxDropOffHeight) + { + angle = R_PointToAngle2(0,0,line->dx,line->dy); // front side dropoff + } + else if (front == actor->z && back < actor->z - actor->MaxDropOffHeight) + { + angle = R_PointToAngle2(line->dx,line->dy,0,0); // back side dropoff + } + else continue; - validcount++; - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - P_BlockLinesIterator(bx, by, PIT_AvoidDropoff); // all contacted lines + // 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 (a.deltax || a.deltay) + if (deltax || deltay) { // [Graf Zahl] I have changed P_TryMove to only apply this logic when // 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 actor->flags5|=MF5_AVOIDINGDROPOFF; - P_DoNewChaseDir(actor, a.deltax, a.deltay); + P_DoNewChaseDir(actor, deltax, deltay); actor->flags5&=~MF5_AVOIDINGDROPOFF; // If moving away from dropoff, set movecount to 1 so that diff --git a/src/p_local.h b/src/p_local.h index 0f2d1ec6a0..44c5ed859c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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); -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 &checkarray, AActor *start=NULL); diff --git a/src/p_map.cpp b/src/p_map.cpp index f02da328ff..180b80835d 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -100,8 +100,6 @@ int tmceilingpic; sector_t *tmceilingsector; bool tmtouchmidtex; -static fixed_t tmfbbox[4]; -static AActor *tmfthing; fixed_t tmffloorz; fixed_t tmfceilingz; 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] - || tmfbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmfbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmfbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) + if (box.Right() <= ld->bbox[BOXLEFT] + || box.Left() >= ld->bbox[BOXRIGHT] + || box.Top() <= ld->bbox[BOXBOTTOM] + || box.Bottom() >= ld->bbox[BOXTOP] ) return true; - if (P_BoxOnLineSide (tmfbbox, ld) != -1) + if (box.BoxOnLineSide (ld) != -1) return true; // A line has been hit @@ -223,17 +221,13 @@ static bool PIT_FindFloorCeiling (line_t *ld) void P_FindFloorCeiling (AActor *actor) { - int xl,xh,yl,yh,bx,by; fixed_t x, y; sector_t *sec; x = actor->x; y = actor->y; - tmfbbox[BOXTOP] = y + actor->radius; - tmfbbox[BOXBOTTOM] = y - actor->radius; - tmfbbox[BOXRIGHT] = x + actor->radius; - tmfbbox[BOXLEFT] = x - actor->radius; + FBoundingBox box(x, y, actor->radius); sec = P_PointInSector (x, y); tmffloorz = tmfdropoffz = sec->floorplane.ZatPoint (x, y); @@ -242,18 +236,15 @@ void P_FindFloorCeiling (AActor *actor) tmffloorsector = sec; tmfceilingpic = sec->ceilingpic; tmfceilingsector = sec; - tmfthing = actor; validcount++; - xl = (tmfbbox[BOXLEFT] - bmaporgx) >> MAPBLOCKSHIFT; - xh = (tmfbbox[BOXRIGHT] - bmaporgx) >> MAPBLOCKSHIFT; - yl = (tmfbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; - yh = (tmfbbox[BOXTOP] - bmaporgy) >> MAPBLOCKSHIFT; + FBlockLinesIterator it(box); + line_t *ld; - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - if (!P_BlockLinesIterator (bx, by, PIT_FindFloorCeiling)) - return; + while ((ld = it.Next())) + { + PIT_FindFloorCeiling(ld, actor, box, x, y); + } 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; tmz = z; - tmfbbox[BOXTOP] = tmbbox[BOXTOP] = y + tmthing->radius; - tmfbbox[BOXBOTTOM] = tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmfbbox[BOXRIGHT] = tmbbox[BOXRIGHT] = x + tmthing->radius; - tmfbbox[BOXLEFT] = tmbbox[BOXLEFT] = x - tmthing->radius; + tmbbox[BOXTOP] = y + tmthing->radius; + tmbbox[BOXBOTTOM] = y - tmthing->radius; + tmbbox[BOXRIGHT] = x + tmthing->radius; + tmbbox[BOXLEFT] = x - tmthing->radius; newsec = P_PointInSector (x,y); ceilingline = NULL; @@ -356,7 +347,6 @@ bool P_TeleportMove (AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefr tmffloorsector = newsec; tmfceilingpic = newsec->ceilingpic; tmfceilingsector = newsec; - tmfthing = tmthing; validcount++; 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; - // 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; + FBoundingBox box(x, y, thing->radius); + FBlockLinesIterator it(box); + line_t *ld; - for (bx=xl ; bx<=xh ; bx++) + while ((ld = it.Next())) { - for (by=yl ; by<=yh ; by++) - { - if (!P_BlockLinesIterator(bx,by,PIT_FindFloorCeiling)) - { - return false; - } - } + PIT_FindFloorCeiling(ld, thing, box, x, y); } 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; 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 (by=yl ; by<=yh ; by++) @@ -609,54 +598,23 @@ int P_GetMoveFactor (const AActor *mo, int *frictionp) // 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 // Adjusts tmfloorz and tmceilingz as lines are contacted // 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; - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) + if (box.Right() <= ld->bbox[BOXLEFT] + || box.Left() >= ld->bbox[BOXRIGHT] + || box.Top() <= ld->bbox[BOXBOTTOM] + || box.Bottom() >= ld->bbox[BOXTOP] ) return true; - if (P_BoxOnLineSide (tmbbox, ld) != -1) + if (box.BoxOnLineSide (ld) != -1) return true; // A line has been hit @@ -1113,51 +1071,6 @@ bool PIT_CheckThing (AActor *thing) // 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; tmy = y; - tmbbox[BOXTOP] = y + thing->radius; - tmbbox[BOXBOTTOM] = y - thing->radius; - tmbbox[BOXRIGHT] = x + thing->radius; - tmbbox[BOXLEFT] = x - thing->radius; + FBoundingBox box(x, y, thing->radius); + + tmbbox[BOXTOP] = box.Top(); + tmbbox[BOXBOTTOM] = box.Bottom(); + tmbbox[BOXRIGHT] = box.Right(); + tmbbox[BOXLEFT] = box.Left(); newsec = P_PointInSector (x,y); ceilingline = BlockingLine = NULL; @@ -1407,19 +1322,18 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y) thing->height = realheight; if (tmflags & MF_NOCLIP) return (BlockingMobj = thingblocker) == NULL; - xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + + FBlockLinesIterator it(box); + line_t *ld; fixed_t thingdropoffz = tmfloorz; //bool onthing = (thingdropoffz != tmdropoffz); tmfloorz = tmdropoffz; - for (bx=xl ; bx<=xh ; bx++) - for (by=yl ; by<=yh ; by++) - if (!P_BlockLinesIterator (bx,by,PIT_CheckLine)) - return false; + while ((ld = it.Next())) + { + if (!PIT_CheckLine(ld, box)) return false; + } if (tmceilingz - tmfloorz < thing->height) return false; @@ -4713,50 +4627,6 @@ void P_DelSeclist (msecnode_t *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 // @@ -4768,18 +4638,8 @@ bool PIT_GetSectors (line_t *ld) void P_CreateSecNodeList (AActor *thing, fixed_t x, fixed_t y) { - int xl, xh, yl, yh, bx, by; 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 // added or verified as needed, m_thing will be set properly. When // 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; } - tmthing = thing; - tmflags = thing->flags; + FBoundingBox box(thing->x, thing->y, thing->radius); + FBlockLinesIterator it(box); + line_t *ld; - tmx = x; - tmy = y; + while ((ld = it.Next())) + { + 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; - tmbbox[BOXBOTTOM] = y - tmthing->radius; - tmbbox[BOXRIGHT] = x + tmthing->radius; - tmbbox[BOXLEFT] = x - tmthing->radius; + if (box.BoxOnLineSide (ld) != -1) + continue; - validcount++; // used to make sure we only process a line once + // This line crosses through the object. - xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; - xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; - yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; - yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + // 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. - for (bx = xl; bx <= xh; bx++) - for (by = yl; by <= yh; by++) - P_BlockLinesIterator (bx,by,PIT_GetSectors); + sector_list = P_AddSecnode (ld->frontsector,thing,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, thing, 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; } } - - // [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) diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 547b854a3f..cce9522f8e 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -677,75 +677,119 @@ void FBlockNode::Release () // -// P_BlockLinesIterator -// 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. +// FBlockLinesIterator // 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; + maxx = _maxx; + miny = _miny; + maxy = _maxy; + Reset(); +} + +FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box) +{ + validcount++; + maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT; + miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT; + maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT; + minx = (box.Left() - bmaporgx) >> MAPBLOCKSHIFT; + Reset(); +} + + +void FBlockLinesIterator::StartBlock(int x, int y) +{ + if (x >= 0 && y >= 0 && x < bmapwidth && y */ - polyblock_t *polyLink; - - 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++) - { - if ((*tempSeg)->linedef->validcount != validcount) - { - (*tempSeg)->linedef->validcount = validcount; - if (!func ((*tempSeg)->linedef)) - return false; - } - } - } - polyLink = polyLink->next; - } - } - /* <-- Polyobj stuff from Hexen */ - - offset = *(blockmap + offset); + curx = x; + cury = y; + int offset = y*bmapwidth + x; + polyLink = PolyBlockMap? PolyBlockMap[offset] : NULL; + polyIndex = 0; // There is an extra entry at the beginning of every block. // Apparently, id had originally intended for it to be used // to keep track of things, but the final code does not do that. - for (list = blockmaplump + offset + 1; *list != -1; list++) - { - line_t *ld = &lines[*list]; + list = blockmaplump + *(blockmap + offset) + 1; + } + else + { + // invalid block + list = NULL; + polyLink = NULL; + } +} - if (ld->validcount != validcount) +line_t *FBlockLinesIterator::Next() +{ + while (true) + { + while (polyLink != NULL) + { + if (polyLink->polyobj) { - ld->validcount = validcount; - - if ( !func(ld) ) - return false; + 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]; + + if (ld->validcount != validcount) + { + ld->validcount = validcount; + return ld; + } + else + { + list++; + } } } + + if (++curx > maxx) + { + curx = minx; + if (++cury > maxy) return NULL; + } + StartBlock(curx, cury); } - return true; // everything was checked } @@ -829,59 +873,62 @@ int ptflags; // are on opposite sides of the trace. // Returns true if earlyout and a solid line hit. // -bool PIT_AddLineIntercepts (line_t *ld) +void P_AddLineIntercepts(int bx, int by) { - int s1; - int s2; - fixed_t frac; - divline_t dl; + FBlockLinesIterator it(bx, by, bx, by, true); + line_t *ld; - // avoid precision problems with two routines - if ( trace.dx > FRACUNIT*16 - || trace.dy > FRACUNIT*16 - || trace.dx < -FRACUNIT*16 - || trace.dy < -FRACUNIT*16) + while ((ld = it.Next())) { - s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); - s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); - } - else - { - s1 = P_PointOnLineSide (trace.x, trace.y, ld); - s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); - } - - if (s1 == s2) - return true; // line isn't crossed - - // hit the line - P_MakeDivline (ld, &dl); - frac = P_InterceptVector (&trace, &dl); + int s1; + int s2; + fixed_t frac; + divline_t dl; - if (frac < 0) - return true; // behind source + // avoid precision problems with two routines + if ( trace.dx > FRACUNIT*16 + || trace.dy > FRACUNIT*16 + || trace.dx < -FRACUNIT*16 + || trace.dy < -FRACUNIT*16) + { + s1 = P_PointOnDivlineSide (ld->v1->x, ld->v1->y, &trace); + s2 = P_PointOnDivlineSide (ld->v2->x, ld->v2->y, &trace); + } + else + { + s1 = P_PointOnLineSide (trace.x, trace.y, ld); + s2 = P_PointOnLineSide (trace.x+trace.dx, trace.y+trace.dy, ld); + } - // try to early out the check - if (earlyout - && frac < FRACUNIT - && !ld->backsector) - { - return false; // stop checking + if (s1 == s2) continue; // line isn't crossed + + // hit the line + P_MakeDivline (ld, &dl); + frac = P_InterceptVector (&trace, &dl); + + if (frac < 0) continue; // behind source + + /* unused code + // try to early out the check + if (earlyout + && frac < FRACUNIT + && !ld->backsector) + { + return false; // stop checking + } + */ + + + intercept_t newintercept; + + newintercept.frac = frac; + newintercept.isaline = true; + newintercept.d.line = ld; + intercepts.Push (newintercept); } - - - intercept_t newintercept; - - newintercept.frac = frac; - newintercept.isaline = true; - newintercept.d.line = ld; - intercepts.Push (newintercept); - - return true; // continue } - // // 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 (!P_BlockLinesIterator (mapx, mapy, PIT_AddLineIntercepts)) - return false; // early out + P_AddLineIntercepts(mapx, mapy); } 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. if (flags & PT_ADDLINES) { - if (!P_BlockLinesIterator (mapx + mapxstep, mapy, PIT_AddLineIntercepts) || - !P_BlockLinesIterator (mapx, mapy + mapystep, PIT_AddLineIntercepts)) - return false; // early out + P_AddLineIntercepts(mapx + mapxstep, mapy); + P_AddLineIntercepts(mapx, mapy + mapystep); } if (flags & PT_ADDTHINGS) @@ -1330,3 +1375,5 @@ static AActor *RoughBlockCheck (AActor *mo, int index) } return NULL; } + + diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index fbc2364a9d..8bff17d990 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3642,6 +3642,7 @@ APlayerPawn *P_SpawnPlayer (mapthing2_t *mthing, bool tempplayer) p->damagecount = 0; p->bonuscount = 0; p->morphTics = 0; + p->MorphedPlayerClass = 0; p->extralight = 0; p->fixedcolormap = 0; p->viewheight = mobj->ViewHeight; diff --git a/src/p_user.cpp b/src/p_user.cpp index 3d8a888d0e..d7d218819e 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -242,6 +242,7 @@ player_s::player_s() attacker(0), extralight(0), morphTics(0), + MorphedPlayerClass(0), PremorphWeapon(0), chickenPeck(0), jumpTics(0), @@ -2415,6 +2416,7 @@ void player_s::Serialize (FArchive &arc) << extralight << fixedcolormap << morphTics + << MorphedPlayerClass << PremorphWeapon << chickenPeck << jumpTics diff --git a/src/po_man.cpp b/src/po_man.cpp index 5c77ab6317..8c41818235 100644 --- a/src/po_man.cpp +++ b/src/po_man.cpp @@ -1068,7 +1068,6 @@ static bool CheckMobjBlocking (seg_t *seg, polyobj_t *po) AActor *mobj; int i, j, k; int left, right, top, bottom; - fixed_t tmbbox[4]; line_t *ld; bool blocked; @@ -1110,19 +1109,16 @@ static bool CheckMobjBlocking (seg_t *seg, polyobj_t *po) checker.Push (mobj); if ((mobj->flags&MF_SOLID) && !(mobj->flags&MF_NOCLIP)) { - tmbbox[BOXTOP] = mobj->y+mobj->radius; - tmbbox[BOXBOTTOM] = mobj->y-mobj->radius; - tmbbox[BOXLEFT] = mobj->x-mobj->radius; - tmbbox[BOXRIGHT] = mobj->x+mobj->radius; + FBoundingBox box(mobj->x, mobj->y, mobj->radius); - if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] - || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] - || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] - || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP]) + if (box.Right() <= ld->bbox[BOXLEFT] + || box.Left() >= ld->bbox[BOXRIGHT] + || box.Top() <= ld->bbox[BOXBOTTOM] + || box.Bottom() >= ld->bbox[BOXTOP]) { continue; } - if (P_BoxOnLineSide(tmbbox, ld) != -1) + if (box.BoxOnLineSide(ld) != -1) { continue; } diff --git a/src/v_video.h b/src/v_video.h index 8f38f15d19..c6c9b5fd9e 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -35,7 +35,6 @@ #define __V_VIDEO_H__ #include "doomtype.h" -#include "m_bbox.h" #include "v_palette.h" #include "v_font.h" diff --git a/src/version.h b/src/version.h index 601b27e89e..5d939fd3bc 100644 --- a/src/version.h +++ b/src/version.h @@ -75,7 +75,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 879 +#define MINSAVEVER 887 #if SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need