mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-27 22:42:57 +00:00
- Removed PT_EARLYOUT from P_PathTraverse because it wasn't used anywhere.
- Rewrote BlockThingsIterator code not to use callbacks anymore. SVN r888 (trunk)
This commit is contained in:
parent
ebd17de30a
commit
0b26377624
7 changed files with 730 additions and 989 deletions
|
@ -1,3 +1,7 @@
|
|||
April 7, 2008 (Changes by Graf Zahl)
|
||||
- Removed PT_EARLYOUT from P_PathTraverse because it wasn't used anywhere.
|
||||
- Rewrote BlockThingsIterator code not to use callbacks anymore.
|
||||
|
||||
April 6, 2008 (Changes by Graf Zahl)
|
||||
- Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but
|
||||
P_FindFloorCeiling never did that.
|
||||
|
|
|
@ -35,58 +35,6 @@ void A_ThrustLower (AActor *);
|
|||
void A_ThrustBlock (AActor *);
|
||||
void A_ThrustImpale (AActor *);
|
||||
|
||||
AActor *tsthing;
|
||||
|
||||
bool PIT_ThrustStompThing (AActor *thing)
|
||||
{
|
||||
fixed_t blockdist;
|
||||
|
||||
if (!(thing->flags & MF_SHOOTABLE) )
|
||||
return true;
|
||||
|
||||
blockdist = thing->radius + tsthing->radius;
|
||||
if ( abs(thing->x - tsthing->x) >= blockdist ||
|
||||
abs(thing->y - tsthing->y) >= blockdist ||
|
||||
(thing->z > tsthing->z+tsthing->height) )
|
||||
return true; // didn't hit it
|
||||
|
||||
if (thing == tsthing)
|
||||
return true; // don't clip against self
|
||||
|
||||
P_DamageMobj (thing, tsthing, tsthing, 10001, NAME_Crush);
|
||||
P_TraceBleed (10001, thing);
|
||||
tsthing->args[1] = 1; // Mark thrust thing as bloody
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P_ThrustSpike (AActor *actor)
|
||||
{
|
||||
static TArray<AActor *> spikebt;
|
||||
|
||||
int xl,xh,yl,yh,bx,by;
|
||||
int x0,x2,y0,y2;
|
||||
|
||||
tsthing = actor;
|
||||
|
||||
x0 = actor->x - actor->radius;
|
||||
x2 = actor->x + actor->radius;
|
||||
y0 = actor->y - actor->radius;
|
||||
y2 = actor->y + actor->radius;
|
||||
|
||||
xl = (x0 - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
xh = (x2 - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yl = (y0 - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yh = (y2 - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
|
||||
spikebt.Clear();
|
||||
|
||||
// stomp on any things contacted
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
for (by = yl; by <= yh; by++)
|
||||
P_BlockThingsIterator (bx, by, PIT_ThrustStompThing, spikebt);
|
||||
}
|
||||
|
||||
// AThrustFloor is just a container for all the spike states.
|
||||
// All the real spikes subclass it.
|
||||
|
||||
|
@ -313,7 +261,19 @@ void A_ThrustBlock (AActor *actor)
|
|||
|
||||
void A_ThrustImpale (AActor *actor)
|
||||
{
|
||||
// Impale all shootables in radius
|
||||
P_ThrustSpike (actor);
|
||||
AActor *thing;
|
||||
FRadiusThingsIterator it(actor->x, actor->y, actor->radius);
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if (!(thing->flags & MF_SHOOTABLE) )
|
||||
continue;
|
||||
|
||||
if (thing == actor)
|
||||
continue; // don't clip against self
|
||||
|
||||
P_DamageMobj (thing, actor, actor, 10001, NAME_Crush);
|
||||
P_TraceBleed (10001, thing);
|
||||
actor->args[1] = 1; // Mark thrust thing as bloody
|
||||
}
|
||||
}
|
||||
|
||||
|
|
236
src/p_enemy.cpp
236
src/p_enemy.cpp
|
@ -2076,64 +2076,6 @@ void A_DoChase (AActor *actor, bool fastchase, FState *meleestate, FState *missi
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// PIT_VileCheck
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static AActor *corpsehit;
|
||||
static AActor *vileobj;
|
||||
static fixed_t viletryx;
|
||||
static fixed_t viletryy;
|
||||
static FState *raisestate;
|
||||
|
||||
static bool PIT_VileCheck (AActor *thing)
|
||||
{
|
||||
int maxdist;
|
||||
bool check;
|
||||
|
||||
if (!(thing->flags & MF_CORPSE) )
|
||||
return true; // not a monster
|
||||
|
||||
if (thing->tics != -1)
|
||||
return true; // not lying still yet
|
||||
|
||||
raisestate = thing->FindState(NAME_Raise);
|
||||
if (raisestate == NULL)
|
||||
return true; // monster doesn't have a raise state
|
||||
|
||||
// This may be a potential problem if this is used by something other
|
||||
// than an Arch Vile.
|
||||
//maxdist = thing->GetDefault()->radius + GetDefault<AArchvile>()->radius;
|
||||
|
||||
// use the current actor's radius instead of the Arch Vile's default.
|
||||
maxdist = thing->GetDefault()->radius + vileobj->radius;
|
||||
|
||||
if ( abs(thing->x - viletryx) > maxdist
|
||||
|| abs(thing->y - viletryy) > maxdist )
|
||||
return true; // not actually touching
|
||||
|
||||
corpsehit = thing;
|
||||
corpsehit->momx = corpsehit->momy = 0;
|
||||
// [RH] Check against real height and radius
|
||||
|
||||
fixed_t oldheight = corpsehit->height;
|
||||
fixed_t oldradius = corpsehit->radius;
|
||||
int oldflags = corpsehit->flags;
|
||||
|
||||
corpsehit->flags |= MF_SOLID;
|
||||
corpsehit->height = corpsehit->GetDefault()->height;
|
||||
check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
|
||||
corpsehit->flags = oldflags;
|
||||
corpsehit->radius = oldradius;
|
||||
corpsehit->height = oldheight;
|
||||
|
||||
return !check;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// P_CheckForResurrection (formerly part of A_VileChase)
|
||||
|
@ -2143,101 +2085,113 @@ static bool PIT_VileCheck (AActor *thing)
|
|||
|
||||
static bool P_CheckForResurrection(AActor *self, bool usevilestates)
|
||||
{
|
||||
static TArray<AActor *> vilebt;
|
||||
int xl, xh, yl, yh;
|
||||
int bx, by;
|
||||
|
||||
const AActor *info;
|
||||
AActor *temp;
|
||||
|
||||
if (self->movedir != DI_NODIR)
|
||||
{
|
||||
const fixed_t absSpeed = abs (self->Speed);
|
||||
fixed_t viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]);
|
||||
fixed_t viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]);
|
||||
AActor *corpsehit;
|
||||
FState *raisestate;
|
||||
|
||||
// check for corpses to raise
|
||||
viletryx = self->x + FixedMul (absSpeed, xspeed[self->movedir]);
|
||||
viletryy = self->y + FixedMul (absSpeed, yspeed[self->movedir]);
|
||||
|
||||
xl = (viletryx - bmaporgx - MAXRADIUS*2)>>MAPBLOCKSHIFT;
|
||||
xh = (viletryx - bmaporgx + MAXRADIUS*2)>>MAPBLOCKSHIFT;
|
||||
yl = (viletryy - bmaporgy - MAXRADIUS*2)>>MAPBLOCKSHIFT;
|
||||
yh = (viletryy - bmaporgy + MAXRADIUS*2)>>MAPBLOCKSHIFT;
|
||||
|
||||
vileobj = self;
|
||||
validcount++;
|
||||
vilebt.Clear();
|
||||
|
||||
for (bx = xl; bx <= xh; bx++)
|
||||
FBlockThingsIterator it(FBoundingBox(viletryx, viletryy, 32*FRACUNIT));
|
||||
while ((corpsehit = it.Next()))
|
||||
{
|
||||
for (by = yl; by <= yh; by++)
|
||||
if (!(corpsehit->flags & MF_CORPSE) )
|
||||
continue; // not a monster
|
||||
|
||||
if (corpsehit->tics != -1)
|
||||
continue; // not lying still yet
|
||||
|
||||
raisestate = corpsehit->FindState(NAME_Raise);
|
||||
if (raisestate == NULL)
|
||||
continue; // monster doesn't have a raise state
|
||||
|
||||
// use the current actor's radius instead of the Arch Vile's default.
|
||||
fixed_t maxdist = corpsehit->GetDefault()->radius + self->radius;
|
||||
|
||||
maxdist = corpsehit-> GetDefault()->radius + self->radius;
|
||||
|
||||
if ( abs(corpsehit-> x - viletryx) > maxdist ||
|
||||
abs(corpsehit-> y - viletryy) > maxdist )
|
||||
continue; // not actually touching
|
||||
|
||||
corpsehit->momx = corpsehit->momy = 0;
|
||||
// [RH] Check against real height and radius
|
||||
|
||||
fixed_t oldheight = corpsehit->height;
|
||||
fixed_t oldradius = corpsehit->radius;
|
||||
int oldflags = corpsehit->flags;
|
||||
|
||||
corpsehit->flags |= MF_SOLID;
|
||||
corpsehit->height = corpsehit->GetDefault()->height;
|
||||
bool check = P_CheckPosition (corpsehit, corpsehit->x, corpsehit->y);
|
||||
corpsehit->flags = oldflags;
|
||||
corpsehit->radius = oldradius;
|
||||
corpsehit->height = oldheight;
|
||||
if (!check) continue;
|
||||
|
||||
// got one!
|
||||
temp = self->target;
|
||||
self->target = corpsehit;
|
||||
A_FaceTarget (self);
|
||||
if (self->flags & MF_FRIENDLY)
|
||||
{
|
||||
// Call PIT_VileCheck to check
|
||||
// whether object is a corpse
|
||||
// that can be raised.
|
||||
if (!P_BlockThingsIterator (bx, by, PIT_VileCheck, vilebt))
|
||||
// If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend)
|
||||
// and the Arch-Vile is currently targetting the resurrected monster the target must be cleared.
|
||||
if (self->lastenemy == temp) self->lastenemy = NULL;
|
||||
if (self->lastenemy == corpsehit) self->lastenemy = NULL;
|
||||
if (temp == self->target) temp = NULL;
|
||||
}
|
||||
self->target = temp;
|
||||
|
||||
// Make the state the monster enters customizable.
|
||||
FState * state = self->FindState(NAME_Heal);
|
||||
if (state != NULL)
|
||||
{
|
||||
self->SetState (state);
|
||||
}
|
||||
else if (usevilestates)
|
||||
{
|
||||
// For Dehacked compatibility this has to use the Arch Vile's
|
||||
// heal state as a default if the actor doesn't define one itself.
|
||||
const PClass *archvile = PClass::FindClass("Archvile");
|
||||
if (archvile != NULL)
|
||||
{
|
||||
// got one!
|
||||
temp = self->target;
|
||||
self->target = corpsehit;
|
||||
A_FaceTarget (self);
|
||||
if (self->flags & MF_FRIENDLY)
|
||||
{
|
||||
// If this is a friendly Arch-Vile (which is turning the resurrected monster into its friend)
|
||||
// and the Arch-Vile is currently targetting the resurrected monster the target must be cleared.
|
||||
if (self->lastenemy == temp) self->lastenemy = NULL;
|
||||
if (temp == self->target) temp = NULL;
|
||||
|
||||
}
|
||||
self->target = temp;
|
||||
|
||||
// Make the state the monster enters customizable.
|
||||
FState * state = self->FindState(NAME_Heal);
|
||||
if (state != NULL)
|
||||
{
|
||||
self->SetState (state);
|
||||
}
|
||||
else if (usevilestates)
|
||||
{
|
||||
// For Dehacked compatibility this has to use the Arch Vile's
|
||||
// heal state as a default if the actor doesn't define one itself.
|
||||
const PClass *archvile = PClass::FindClass("Archvile");
|
||||
if (archvile != NULL)
|
||||
{
|
||||
self->SetState (archvile->ActorInfo->FindState(NAME_Heal));
|
||||
}
|
||||
}
|
||||
S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
|
||||
info = corpsehit->GetDefault ();
|
||||
|
||||
corpsehit->SetState (raisestate);
|
||||
corpsehit->height = info->height; // [RH] Use real mobj height
|
||||
corpsehit->radius = info->radius; // [RH] Use real radius
|
||||
/*
|
||||
// Make raised corpses look ghostly
|
||||
if (corpsehit->alpha > TRANSLUC50)
|
||||
corpsehit->alpha /= 2;
|
||||
*/
|
||||
corpsehit->flags = info->flags;
|
||||
corpsehit->flags2 = info->flags2;
|
||||
corpsehit->flags3 = info->flags3;
|
||||
corpsehit->flags4 = info->flags4;
|
||||
corpsehit->health = info->health;
|
||||
corpsehit->target = NULL;
|
||||
corpsehit->lastenemy = NULL;
|
||||
|
||||
// [RH] If it's a monster, it gets to count as another kill
|
||||
if (corpsehit->CountsAsKill())
|
||||
{
|
||||
level.total_monsters++;
|
||||
}
|
||||
|
||||
// You are the Archvile's minion now, so hate what it hates
|
||||
corpsehit->CopyFriendliness (self, false);
|
||||
|
||||
|
||||
return true;
|
||||
self->SetState (archvile->ActorInfo->FindState(NAME_Heal));
|
||||
}
|
||||
}
|
||||
S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
|
||||
info = corpsehit->GetDefault ();
|
||||
|
||||
corpsehit->SetState (raisestate);
|
||||
corpsehit->height = info->height; // [RH] Use real mobj height
|
||||
corpsehit->radius = info->radius; // [RH] Use real radius
|
||||
/*
|
||||
// Make raised corpses look ghostly
|
||||
if (corpsehit->alpha > TRANSLUC50)
|
||||
corpsehit->alpha /= 2;
|
||||
*/
|
||||
corpsehit->flags = info->flags;
|
||||
corpsehit->flags2 = info->flags2;
|
||||
corpsehit->flags3 = info->flags3;
|
||||
corpsehit->flags4 = info->flags4;
|
||||
corpsehit->health = info->health;
|
||||
corpsehit->target = NULL;
|
||||
corpsehit->lastenemy = NULL;
|
||||
|
||||
// [RH] If it's a monster, it gets to count as another kill
|
||||
if (corpsehit->CountsAsKill())
|
||||
{
|
||||
level.total_monsters++;
|
||||
}
|
||||
|
||||
// You are the Archvile's minion now, so hate what it hates
|
||||
corpsehit->CopyFriendliness (self, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -255,12 +255,48 @@ public:
|
|||
void Reset() { StartBlock(minx, miny); }
|
||||
};
|
||||
|
||||
bool P_BlockThingsIterator (int x, int y, bool(*func)(AActor*), TArray<AActor *> &checkarray, AActor *start=NULL);
|
||||
class FBlockThingsIterator
|
||||
{
|
||||
typedef TArray<AActor *> BTChecked;
|
||||
|
||||
static TDeletingArray< BTChecked* > FreeBTChecked;
|
||||
|
||||
|
||||
int minx, maxx;
|
||||
int miny, maxy;
|
||||
|
||||
int curx, cury;
|
||||
|
||||
bool dontfreecheck;
|
||||
BTChecked *checkarray;
|
||||
|
||||
FBlockNode *block;
|
||||
|
||||
static BTChecked *GetCheckArray();
|
||||
void FreeCheckArray();
|
||||
void StartBlock(int x, int y);
|
||||
|
||||
public:
|
||||
FBlockThingsIterator(int minx, int miny, int maxx, int maxy, TArray<AActor *> *check = NULL);
|
||||
FBlockThingsIterator(const FBoundingBox &box);
|
||||
~FBlockThingsIterator()
|
||||
{
|
||||
if (!dontfreecheck) FreeCheckArray();
|
||||
}
|
||||
AActor *Next();
|
||||
void Reset() { StartBlock(minx, miny); }
|
||||
};
|
||||
|
||||
class FRadiusThingsIterator : public FBlockThingsIterator
|
||||
{
|
||||
fixed_t X, Y, Radius;
|
||||
public:
|
||||
FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius);
|
||||
AActor *Next();
|
||||
};
|
||||
|
||||
#define PT_ADDLINES 1
|
||||
#define PT_ADDTHINGS 2
|
||||
#define PT_EARLYOUT 4
|
||||
|
||||
extern divline_t trace;
|
||||
|
||||
|
|
936
src/p_map.cpp
936
src/p_map.cpp
File diff suppressed because it is too large
Load diff
356
src/p_maputl.cpp
356
src/p_maputl.cpp
|
@ -676,9 +676,11 @@ void FBlockNode::Release ()
|
|||
//
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockLinesIterator
|
||||
//
|
||||
//===========================================================================
|
||||
extern polyblock_t **PolyBlockMap;
|
||||
|
||||
FBlockLinesIterator::FBlockLinesIterator(int _minx, int _miny, int _maxx, int _maxy, bool keepvalidcount)
|
||||
|
@ -702,12 +704,18 @@ FBlockLinesIterator::FBlockLinesIterator(const FBoundingBox &box)
|
|||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockLinesIterator :: StartBlock
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FBlockLinesIterator::StartBlock(int x, int y)
|
||||
{
|
||||
curx = x;
|
||||
cury = y;
|
||||
if (x >= 0 && y >= 0 && x < bmapwidth && y <bmapheight)
|
||||
{
|
||||
curx = x;
|
||||
cury = y;
|
||||
int offset = y*bmapwidth + x;
|
||||
polyLink = PolyBlockMap? PolyBlockMap[offset] : NULL;
|
||||
polyIndex = 0;
|
||||
|
@ -725,6 +733,12 @@ void FBlockLinesIterator::StartBlock(int x, int y)
|
|||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockLinesIterator :: Next
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
line_t *FBlockLinesIterator::Next()
|
||||
{
|
||||
while (true)
|
||||
|
@ -792,67 +806,165 @@ line_t *FBlockLinesIterator::Next()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// P_BlockThingsIterator
|
||||
// FBlockThingsIterator :: GetCheckArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
bool P_BlockThingsIterator (int x, int y, bool(*func)(AActor*), TArray<AActor *> &checkarray, AActor *actor)
|
||||
TDeletingArray< FBlockThingsIterator::BTChecked* > FBlockThingsIterator::FreeBTChecked;
|
||||
|
||||
FBlockThingsIterator::BTChecked *FBlockThingsIterator::GetCheckArray()
|
||||
{
|
||||
if ((unsigned int)x >= (unsigned int)bmapwidth ||
|
||||
(unsigned int)y >= (unsigned int)bmapheight)
|
||||
if (FreeBTChecked.Size() != 0)
|
||||
{
|
||||
return true;
|
||||
BTChecked *ret;
|
||||
FreeBTChecked.Pop(ret);
|
||||
ret->Clear();
|
||||
return ret;
|
||||
}
|
||||
return new BTChecked();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: FreeCheckArray
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FBlockThingsIterator::FreeCheckArray()
|
||||
{
|
||||
FreeBTChecked.Push(checkarray);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: FBlockThingsIterator
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FBlockThingsIterator::FBlockThingsIterator(int _minx, int _miny, int _maxx, int _maxy, TArray<AActor *> *Check)
|
||||
{
|
||||
if (Check != NULL)
|
||||
{
|
||||
checkarray = Check;
|
||||
dontfreecheck = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
FBlockNode *block;
|
||||
int index = y*bmapwidth + x;
|
||||
checkarray = GetCheckArray();
|
||||
}
|
||||
minx = _minx;
|
||||
maxx = _maxx;
|
||||
miny = _miny;
|
||||
maxy = _maxy;
|
||||
Reset();
|
||||
}
|
||||
|
||||
if (actor == NULL)
|
||||
{
|
||||
block = blocklinks[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
block = actor->BlockNode;
|
||||
while (block != NULL && block->BlockIndex != index)
|
||||
{
|
||||
block = block->NextBlock;
|
||||
}
|
||||
if (block != NULL)
|
||||
{
|
||||
block = block->NextActor;
|
||||
}
|
||||
}
|
||||
FBlockThingsIterator::FBlockThingsIterator(const FBoundingBox &box)
|
||||
{
|
||||
checkarray = GetCheckArray();
|
||||
maxy = (box.Top() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
miny = (box.Bottom() - bmaporgy) >> MAPBLOCKSHIFT;
|
||||
maxx = (box.Right() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||
minx = (box.Left() - bmaporgx) >> MAPBLOCKSHIFT;
|
||||
Reset();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: StartBlock
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void FBlockThingsIterator::StartBlock(int x, int y)
|
||||
{
|
||||
if (x >= 0 && y >= 0 && x < bmapwidth && y <bmapheight)
|
||||
{
|
||||
curx = x;
|
||||
cury = y;
|
||||
block = blocklinks[y*bmapwidth + x];
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid block
|
||||
block = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FBlockThingsIterator :: Next
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
AActor *FBlockThingsIterator::Next()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
while (block != NULL)
|
||||
{
|
||||
FBlockNode *next = block->NextActor;
|
||||
AActor *me = block->Me;
|
||||
int i;
|
||||
|
||||
block = block->NextActor;
|
||||
// Don't recheck things that were already checked
|
||||
for (i = (int)checkarray.Size() - 1; i >= 0; --i)
|
||||
for (i = (int)checkarray->Size() - 1; i >= 0; --i)
|
||||
{
|
||||
if (checkarray[i] == block->Me)
|
||||
if ((*checkarray)[i] == me)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i < 0)
|
||||
{
|
||||
checkarray.Push (block->Me);
|
||||
if (!func (block->Me))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
checkarray->Push (me);
|
||||
return me;
|
||||
}
|
||||
block = next;
|
||||
}
|
||||
|
||||
if (++curx > maxx)
|
||||
{
|
||||
curx = minx;
|
||||
if (++cury > maxy) return NULL;
|
||||
}
|
||||
StartBlock(curx, cury);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRadiusThingsIterator :: Next
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
FRadiusThingsIterator::FRadiusThingsIterator(fixed_t x, fixed_t y, fixed_t radius)
|
||||
: FBlockThingsIterator(FBoundingBox(x, y, radius))
|
||||
{
|
||||
X = x;
|
||||
Y = y;
|
||||
Radius = radius;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FRadiusThingsIterator :: Next
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
AActor *FRadiusThingsIterator::Next()
|
||||
{
|
||||
AActor *actor;
|
||||
while ((actor = FBlockThingsIterator::Next()))
|
||||
{
|
||||
fixed_t blockdist = actor->radius + Radius;
|
||||
if ( abs(actor->x - X) < blockdist && abs(actor->y - Y) < blockdist)
|
||||
return actor;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// INTERCEPT ROUTINES
|
||||
|
@ -860,7 +972,6 @@ bool P_BlockThingsIterator (int x, int y, bool(*func)(AActor*), TArray<AActor *>
|
|||
TArray<intercept_t> intercepts (128);
|
||||
|
||||
divline_t trace;
|
||||
INTBOOL earlyout;
|
||||
int ptflags;
|
||||
|
||||
//
|
||||
|
@ -871,7 +982,6 @@ int ptflags;
|
|||
//
|
||||
// A line is crossed if its endpoints
|
||||
// are on opposite sides of the trace.
|
||||
// Returns true if earlyout and a solid line hit.
|
||||
//
|
||||
void P_AddLineIntercepts(int bx, int by)
|
||||
{
|
||||
|
@ -908,17 +1018,6 @@ void P_AddLineIntercepts(int bx, int by)
|
|||
|
||||
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;
|
||||
|
@ -932,89 +1031,91 @@ void P_AddLineIntercepts(int bx, int by)
|
|||
//
|
||||
// PIT_AddThingIntercepts
|
||||
//
|
||||
bool PIT_AddThingIntercepts (AActor* thing)
|
||||
void P_AddThingIntercepts (int bx, int by, TArray<AActor*> &checkbt)
|
||||
{
|
||||
int numfronts = 0;
|
||||
divline_t line;
|
||||
int i;
|
||||
FBlockThingsIterator it(bx, by, bx, by, &checkbt);
|
||||
AActor *thing;
|
||||
|
||||
// [RH] Don't check a corner to corner crossection for hit.
|
||||
// Instead, check against the actual bounding box.
|
||||
|
||||
// There's probably a smarter way to determine which two sides
|
||||
// of the thing face the trace than by trying all four sides...
|
||||
for (i = 0; i < 4; ++i)
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
switch (i)
|
||||
int numfronts = 0;
|
||||
divline_t line;
|
||||
int i;
|
||||
|
||||
// [RH] Don't check a corner to corner crossection for hit.
|
||||
// Instead, check against the actual bounding box.
|
||||
|
||||
// There's probably a smarter way to determine which two sides
|
||||
// of the thing face the trace than by trying all four sides...
|
||||
for (i = 0; i < 4; ++i)
|
||||
{
|
||||
case 0: // Top edge
|
||||
line.x = thing->x + thing->radius;
|
||||
line.y = thing->y + thing->radius;
|
||||
line.dx = -thing->radius * 2;
|
||||
line.dy = 0;
|
||||
break;
|
||||
|
||||
case 1: // Right edge
|
||||
line.x = thing->x + thing->radius;
|
||||
line.y = thing->y - thing->radius;
|
||||
line.dx = 0;
|
||||
line.dy = thing->radius * 2;
|
||||
break;
|
||||
|
||||
case 2: // Bottom edge
|
||||
line.x = thing->x - thing->radius;
|
||||
line.y = thing->y - thing->radius;
|
||||
line.dx = thing->radius * 2;
|
||||
line.dy = 0;
|
||||
break;
|
||||
|
||||
case 3: // Left edge
|
||||
line.x = thing->x - thing->radius;
|
||||
line.y = thing->y + thing->radius;
|
||||
line.dx = 0;
|
||||
line.dy = thing->radius * -2;
|
||||
break;
|
||||
}
|
||||
// Check if this side is facing the trace origin
|
||||
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
|
||||
{
|
||||
numfronts++;
|
||||
|
||||
// If it is, see if the trace crosses it
|
||||
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
||||
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
||||
switch (i)
|
||||
{
|
||||
// It's a hit
|
||||
fixed_t frac = P_InterceptVector (&trace, &line);
|
||||
if (frac < 0)
|
||||
{ // behind source
|
||||
return true;
|
||||
}
|
||||
case 0: // Top edge
|
||||
line.x = thing->x + thing->radius;
|
||||
line.y = thing->y + thing->radius;
|
||||
line.dx = -thing->radius * 2;
|
||||
line.dy = 0;
|
||||
break;
|
||||
|
||||
intercept_t newintercept;
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
return true; // keep going
|
||||
case 1: // Right edge
|
||||
line.x = thing->x + thing->radius;
|
||||
line.y = thing->y - thing->radius;
|
||||
line.dx = 0;
|
||||
line.dy = thing->radius * 2;
|
||||
break;
|
||||
|
||||
case 2: // Bottom edge
|
||||
line.x = thing->x - thing->radius;
|
||||
line.y = thing->y - thing->radius;
|
||||
line.dx = thing->radius * 2;
|
||||
line.dy = 0;
|
||||
break;
|
||||
|
||||
case 3: // Left edge
|
||||
line.x = thing->x - thing->radius;
|
||||
line.y = thing->y + thing->radius;
|
||||
line.dx = 0;
|
||||
line.dy = thing->radius * -2;
|
||||
break;
|
||||
}
|
||||
// Check if this side is facing the trace origin
|
||||
if (P_PointOnDivlineSide (trace.x, trace.y, &line) == 0)
|
||||
{
|
||||
numfronts++;
|
||||
|
||||
// If it is, see if the trace crosses it
|
||||
if (P_PointOnDivlineSide (line.x, line.y, &trace) !=
|
||||
P_PointOnDivlineSide (line.x + line.dx, line.y + line.dy, &trace))
|
||||
{
|
||||
// It's a hit
|
||||
fixed_t frac = P_InterceptVector (&trace, &line);
|
||||
if (frac < 0)
|
||||
{ // behind source
|
||||
continue;
|
||||
}
|
||||
|
||||
intercept_t newintercept;
|
||||
newintercept.frac = frac;
|
||||
newintercept.isaline = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If none of the sides was facing the trace, then the trace
|
||||
// must have started inside the box, so add it as an intercept.
|
||||
if (numfronts == 0)
|
||||
{
|
||||
intercept_t newintercept;
|
||||
newintercept.frac = 0;
|
||||
newintercept.isaline = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
return true; // keep going
|
||||
// If none of the sides was facing the trace, then the trace
|
||||
// must have started inside the box, so add it as an intercept.
|
||||
if (numfronts == 0)
|
||||
{
|
||||
intercept_t newintercept;
|
||||
newintercept.frac = 0;
|
||||
newintercept.isaline = false;
|
||||
newintercept.d.thing = thing;
|
||||
intercepts.Push (newintercept);
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't hit it
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1093,8 +1194,6 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
|
||||
int count;
|
||||
|
||||
earlyout = flags & PT_EARLYOUT;
|
||||
|
||||
validcount++;
|
||||
intercepts.Clear ();
|
||||
pathbt.Clear ();
|
||||
|
@ -1197,8 +1296,7 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
if (!P_BlockThingsIterator (mapx, mapy, PIT_AddThingIntercepts, pathbt))
|
||||
return false; // early out
|
||||
P_AddThingIntercepts(mapx, mapy, pathbt);
|
||||
}
|
||||
|
||||
if (mapx == xt2 && mapy == yt2)
|
||||
|
@ -1236,9 +1334,8 @@ bool P_PathTraverse (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags,
|
|||
|
||||
if (flags & PT_ADDTHINGS)
|
||||
{
|
||||
if (!P_BlockThingsIterator (mapx + mapxstep, mapy, PIT_AddThingIntercepts, pathbt) ||
|
||||
!P_BlockThingsIterator (mapx, mapy + mapystep, PIT_AddThingIntercepts, pathbt))
|
||||
return false; // early out
|
||||
P_AddThingIntercepts(mapx + mapxstep, mapy, pathbt);
|
||||
P_AddThingIntercepts(mapx, mapy + mapystep, pathbt);
|
||||
}
|
||||
xintercept += xstep;
|
||||
yintercept += ystep;
|
||||
|
@ -1376,4 +1473,3 @@ static AActor *RoughBlockCheck (AActor *mo, int index)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1684,58 +1684,17 @@ DPusher::DPusher (DPusher::EPusher type, line_t *l, int magnitude, int angle,
|
|||
m_Affectee = affectee;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
//
|
||||
// PIT_PushThing determines the angle and magnitude of the effect.
|
||||
// The object's x and y momentum values are changed.
|
||||
//
|
||||
// tmpusher belongs to the point source (MT_PUSH/MT_PULL).
|
||||
//
|
||||
|
||||
DPusher *tmpusher; // pusher structure for blockmap searches
|
||||
|
||||
bool PIT_PushThing (AActor *thing)
|
||||
{
|
||||
if ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP))
|
||||
{
|
||||
int sx = tmpusher->m_X;
|
||||
int sy = tmpusher->m_Y;
|
||||
int dist = P_AproxDistance (thing->x - sx,thing->y - sy);
|
||||
int speed = (tmpusher->m_Magnitude -
|
||||
((dist>>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1);
|
||||
|
||||
// If speed <= 0, you're outside the effective radius. You also have
|
||||
// to be able to see the push/pull source point.
|
||||
|
||||
if ((speed > 0) && (P_CheckSight (thing, tmpusher->m_Source, 1)))
|
||||
{
|
||||
angle_t pushangle = R_PointToAngle2 (thing->x, thing->y, sx, sy);
|
||||
if (tmpusher->m_Source->IsA (RUNTIME_CLASS(APointPusher)))
|
||||
pushangle += ANG180; // away
|
||||
pushangle >>= ANGLETOFINESHIFT;
|
||||
thing->momx += FixedMul (speed, finecosine[pushangle]);
|
||||
thing->momy += FixedMul (speed, finesine[pushangle]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
//
|
||||
// T_Pusher looks for all objects that are inside the radius of
|
||||
// the effect.
|
||||
//
|
||||
extern fixed_t tmbbox[4];
|
||||
|
||||
void DPusher::Tick ()
|
||||
{
|
||||
static TArray<AActor *> pushbt;
|
||||
sector_t *sec;
|
||||
AActor *thing;
|
||||
msecnode_t *node;
|
||||
int xspeed,yspeed;
|
||||
int xl,xh,yl,yh,bx,by;
|
||||
int radius;
|
||||
int ht;
|
||||
|
||||
if (!var_pushers)
|
||||
|
@ -1773,22 +1732,32 @@ void DPusher::Tick ()
|
|||
// Seek out all pushable things within the force radius of this
|
||||
// point pusher. Crosses sectors, so use blockmap.
|
||||
|
||||
tmpusher = this; // MT_PUSH/MT_PULL point source
|
||||
radius = m_Radius; // where force goes to zero
|
||||
tmbbox[BOXTOP] = m_Y + radius;
|
||||
tmbbox[BOXBOTTOM] = m_Y - radius;
|
||||
tmbbox[BOXRIGHT] = m_X + radius;
|
||||
tmbbox[BOXLEFT] = m_X - radius;
|
||||
FBlockThingsIterator it(FBoundingBox(m_X, m_Y, m_Radius));
|
||||
AActor *thing;
|
||||
|
||||
pushbt.Clear();
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP))
|
||||
{
|
||||
int sx = m_X;
|
||||
int sy = m_Y;
|
||||
int dist = P_AproxDistance (thing->x - sx,thing->y - sy);
|
||||
int speed = (m_Magnitude - ((dist>>FRACBITS)>>1))<<(FRACBITS-PUSH_FACTOR-1);
|
||||
|
||||
xl = (tmbbox[BOXLEFT] - bmaporgx - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
xh = (tmbbox[BOXRIGHT] - bmaporgx + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yl = (tmbbox[BOXBOTTOM] - bmaporgy - MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
yh = (tmbbox[BOXTOP] - bmaporgy + MAXRADIUS)>>MAPBLOCKSHIFT;
|
||||
for (bx=xl ; bx<=xh ; bx++)
|
||||
for (by=yl ; by<=yh ; by++)
|
||||
P_BlockThingsIterator (bx, by, PIT_PushThing, pushbt);
|
||||
// If speed <= 0, you're outside the effective radius. You also have
|
||||
// to be able to see the push/pull source point.
|
||||
|
||||
if ((speed > 0) && (P_CheckSight (thing, m_Source, 1)))
|
||||
{
|
||||
angle_t pushangle = R_PointToAngle2 (thing->x, thing->y, sx, sy);
|
||||
if (m_Source->IsA (RUNTIME_CLASS(APointPusher)))
|
||||
pushangle += ANG180; // away
|
||||
pushangle >>= ANGLETOFINESHIFT;
|
||||
thing->momx += FixedMul (speed, finecosine[pushangle]);
|
||||
thing->momy += FixedMul (speed, finesine[pushangle]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue