- next round of refactoring.

This contains some advance work for handling line-to-line portals in A_PainShootSkull.
This function is special because it performs a map check itself instead of using one of the common functions from p_map.cpp, like most of the rest of the game code.
This commit is contained in:
Christoph Oelckers 2016-01-18 16:49:24 +01:00
parent b63eb391f7
commit 2b5e5b6bc3
8 changed files with 91 additions and 50 deletions

View file

@ -1360,6 +1360,14 @@ inline T *Spawn (const fixedvec3 &pos, replace_t allowreplacement)
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), pos.x, pos.y, pos.z, allowreplacement));
}
inline fixedvec2 Vec2Angle(fixed_t length, angle_t angle)
{
fixedvec2 ret = { FixedMul(length, finecosine[angle >> ANGLETOFINESHIFT]),
FixedMul(length, finesine[angle >> ANGLETOFINESHIFT]) };
return ret;
}
void PrintMiscActorInfo(AActor * query);
#define S_FREETARGMOBJ 1

View file

@ -55,9 +55,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainScream)
{
fixed_t x;
for (x = self->x - 196*FRACUNIT; x < self->x + 320*FRACUNIT; x += 8*FRACUNIT)
for (x = self->X() - 196*FRACUNIT; x < self->X() + 320*FRACUNIT; x += 8*FRACUNIT)
{
BrainishExplosion (x, self->y - 320*FRACUNIT,
BrainishExplosion (x, self->Y() - 320*FRACUNIT,
128 + (pr_brainscream() << (FRACBITS + 1)));
}
S_Sound (self, CHAN_VOICE, "brain/death", 1, ATTN_NONE);
@ -65,9 +65,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_BrainScream)
DEFINE_ACTION_FUNCTION(AActor, A_BrainExplode)
{
fixed_t x = self->x + pr_brainexplode.Random2()*2048;
fixed_t x = self->X() + pr_brainexplode.Random2()*2048;
fixed_t z = 128 + pr_brainexplode()*2*FRACUNIT;
BrainishExplosion (x, self->y, z);
BrainishExplosion (x, self->Y(), z);
}
DEFINE_ACTION_FUNCTION(AActor, A_BrainDie)
@ -140,11 +140,11 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BrainSpit)
}
else if (abs(spit->vely) > abs(spit->velx))
{
spit->special2 = (targ->y - self->y) / spit->vely;
spit->special2 = (targ->Y() - self->Y()) / spit->vely;
}
else
{
spit->special2 = (targ->x - self->x) / spit->velx;
spit->special2 = (targ->X() - self->X()) / spit->velx;
}
// [GZ] Calculates when the projectile will have reached destination
spit->special2 += level.maptime;
@ -185,7 +185,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
if (spawntype != NULL)
{
fog = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
fog = Spawn (spawntype, targ->X(), targ->Y(), targ->Z(), ALLOW_REPLACE);
if (fog != NULL) S_Sound (fog, CHAN_BODY, sound, 1, ATTN_NORM);
}
@ -256,7 +256,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
spawntype = PClass::FindClass(SpawnName);
if (spawntype != NULL)
{
newmobj = Spawn (spawntype, targ->x, targ->y, targ->z, ALLOW_REPLACE);
newmobj = Spawn (spawntype, targ->X(), targ->Y(), targ->Z(), ALLOW_REPLACE);
if (newmobj != NULL)
{
// Make the new monster hate what the boss eye hates
@ -275,7 +275,7 @@ static void SpawnFly(AActor *self, const PClass *spawntype, FSoundID sound)
if (!(newmobj->ObjectFlags & OF_EuthanizeMe))
{
// telefrag anything in this spot
P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true);
P_TeleportMove (newmobj, newmobj->X(), newmobj->Y(), newmobj->Z(), true);
}
newmobj->flags4 |= MF4_BOSSSPAWNED;
}

View file

@ -612,8 +612,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_BFGSpray)
if (linetarget != NULL)
{
AActor *spray = Spawn(spraytype, linetarget->x, linetarget->y,
linetarget->z + (linetarget->height >> 2), ALLOW_REPLACE);
AActor *spray = Spawn(spraytype, linetarget->X(), linetarget->Y(),
linetarget->Z() + (linetarget->height >> 2), ALLOW_REPLACE);
int dmgFlags = 0;
FName dmgType = NAME_BFGSplash;

View file

@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
P_CheckSplash(self, 128<<FRACBITS);
// Now launch mushroom cloud
AActor *target = Spawn("Mapspot", 0, 0, 0, NO_REPLACE); // We need something to aim at.
AActor *target = Spawn("Mapspot", self->X(), self->Y(), self->Z(), NO_REPLACE); // We need something to aim at.
AActor *master = (flags & MSF_DontHurt) ? (AActor*)(self->target) : self;
target->height = self->height;
for (i = -n; i <= n; i += 8)
@ -153,9 +153,9 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom)
for (j = -n; j <= n; j += 8)
{
AActor *mo;
target->x = self->x + (i << FRACBITS); // Aim in many directions from source
target->y = self->y + (j << FRACBITS);
target->z = self->z + (P_AproxDistance(i,j) * vrange); // Aim up fairly high
target->x = self->X() + (i << FRACBITS); // Aim in many directions from source
target->y = self->Y() + (j << FRACBITS);
target->z = self->Z() + (P_AproxDistance(i,j) * vrange); // Aim up fairly high
if ((flags & MSF_Classic) || // Flag explicitely set, or no flags and compat options
(flags == 0 && (self->state->DefineFlags & SDF_DEHACKED) && (i_compatflags & COMPATF_MUSHROOM)))
{ // Use old function for MBF compatibility

View file

@ -41,7 +41,7 @@ void A_SkullAttack(AActor *self, fixed_t speed)
if (dist < 1)
dist = 1;
self->velz = (dest->z + (dest->height>>1) - self->z) / dist;
self->velz = (dest->Z() + (dest->height>>1) - self->Z()) / dist;
}
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SkullAttack)

View file

@ -35,17 +35,14 @@ enum PA_Flags
//
void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype, int flags = 0, int limit = -1)
{
fixed_t x, y, z;
AActor *other;
angle_t an;
int prestep;
if (spawntype == NULL) return;
if (self->DamageType==NAME_Massacre) return;
// [RH] check to make sure it's not too close to the ceiling
if (self->z + self->height + 8*FRACUNIT > self->ceilingz)
if (self->Top() + 8*FRACUNIT > self->ceilingz)
{
if (self->flags & MF_FLOAT)
{
@ -76,47 +73,67 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype, int
}
// okay, there's room for another one
an = angle >> ANGLETOFINESHIFT;
prestep = 4*FRACUNIT +
3*(self->radius + GetDefaultByType(spawntype)->radius)/2;
x = self->x + FixedMul (prestep, finecosine[an]);
y = self->y + FixedMul (prestep, finesine[an]);
z = self->z + 8*FRACUNIT;
// Check whether the Lost Soul is being fired through a 1-sided // phares
// wall or an impassible line, or a "monsters can't cross" line.// |
// If it is, then we don't allow the spawn. // V
FBoundingBox box(MIN(self->x, x), MIN(self->y, y), MAX(self->x, x), MAX(self->y, y));
FBlockLinesIterator it(box);
line_t *ld;
// NOTE: The following code contains some advance work for line-to-line portals which is currenty inactive.
while ((ld = it.Next()))
fixedvec2 dist = Vec2Angle(prestep, angle);
fixedvec3 pos = self->Vec3Offset(dist.x, dist.y, 8 * FRACUNIT, true);
fixedvec3 src = { self->X(), self->Y(), self->Z() };
for (int i = 0; i < 2; i++)
{
if (!(ld->flags & ML_TWOSIDED) ||
(ld->flags & (ML_BLOCKING|ML_BLOCKMONSTERS|ML_BLOCKEVERYTHING)))
// Check whether the Lost Soul is being fired through a 1-sided // phares
// wall or an impassible line, or a "monsters can't cross" line.// |
// If it is, then we don't allow the spawn. // V
FBoundingBox box(MIN(src.x, pos.x), MIN(src.y, pos.y), MAX(src.x, pos.x), MAX(src.y, pos.y));
FBlockLinesIterator it(box);
line_t *ld;
bool inportal = false;
while ((ld = it.Next()))
{
if (!(box.Left() > ld->bbox[BOXRIGHT] ||
box.Right() < ld->bbox[BOXLEFT] ||
box.Top() < ld->bbox[BOXBOTTOM] ||
box.Bottom() > ld->bbox[BOXTOP]))
if (ld->isLinePortal() && i == 0)
{
if (P_PointOnLineSidePrecise(self->x,self->y,ld) != P_PointOnLineSidePrecise(x,y,ld))
return; // line blocks trajectory // ^
if (P_PointOnLineSidePrecise(src.x, src.y, ld) == 0 &&
P_PointOnLineSidePrecise(pos.x, pos.y, ld) == 1)
{
// crossed a portal line from front to back, we need to repeat the check on the other side as well.
inportal = true;
}
}
else 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_PointOnLineSidePrecise(src.x, src.y, ld) != P_PointOnLineSidePrecise(pos.x, pos.y, ld))
return; // line blocks trajectory // ^
}
}
}
if (!inportal) break;
// recalculate position and redo the check on the other side of the portal
pos = self->Vec3Offset(dist.x, dist.y, 8 * FRACUNIT, false);
src.x = pos.x - dist.x;
src.y = pos.y - dist.y;
}
other = Spawn (spawntype, x, y, z, ALLOW_REPLACE);
other = Spawn (spawntype, pos.x, pos.y, pos.z, ALLOW_REPLACE);
// Check to see if the new Lost Soul's z value is above the
// ceiling of its new sector, or below the floor. If so, kill it.
if ((other->z >
(other->Sector->ceilingplane.ZatPoint (other->x, other->y) - other->height)) ||
(other->z < other->Sector->floorplane.ZatPoint (other->x, other->y)))
if ((other->Z() >
(other->Sector->HighestCeiling(other) - other->height)) ||
(other->Z() < other->Sector->LowestFloor(other)))
{
// kill it immediately
P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);// ^
@ -125,7 +142,7 @@ void A_PainShootSkull (AActor *self, angle_t angle, const PClass *spawntype, int
// Check for movements.
if (!P_CheckPosition (other, other->x, other->y))
if (!P_CheckPosition (other, other->X(), other->Y()))
{
// kill it immediately
P_DamageMobj (other, self, self, TELEFRAG_DAMAGE, NAME_None);

View file

@ -254,10 +254,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard)
{
AActor *mo;
mo = Spawn("Wizard", self->x, self->y, self->z, ALLOW_REPLACE);
mo = Spawn("Wizard", self->X(), self->Y(), self->Z(), ALLOW_REPLACE);
if (mo != NULL)
{
mo->z -= mo->GetDefault()->height/2;
mo->SetZ(mo->Z() - mo->GetDefault()->height / 2, false);
if (!P_TestMobjLocation (mo))
{ // Didn't fit
mo->ClearCounters();
@ -272,7 +272,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_GenWizard)
self->flags &= ~MF_MISSILE;
mo->master = self->target;
// Heretic did not offset it by TELEFOGHEIGHT, so I won't either.
Spawn<ATeleportFog> (self->x, self->y, self->z, ALLOW_REPLACE);
Spawn<ATeleportFog> (self->X(), self->Y(), self->Z(), ALLOW_REPLACE);
}
}
}

View file

@ -683,6 +683,17 @@ struct sector_t
return pos == floor? floorplane:ceilingplane;
}
fixed_t HighestCeiling(AActor *a) const
{
return ceilingplane.ZatPoint(a);
}
fixed_t LowestFloor(AActor *a) const
{
return floorplane.ZatPoint(a);
}
bool isSecret() const
{
return !!(Flags & SECF_SECRET);
@ -977,6 +988,11 @@ struct line_t
sector_t *frontsector, *backsector;
int validcount; // if == validcount, already checked
int locknumber; // [Dusk] lock number for special
bool isLinePortal() const
{
return false;
}
};
// phares 3/14/98