mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 23:02:08 +00:00
- 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:
parent
b63eb391f7
commit
2b5e5b6bc3
8 changed files with 91 additions and 50 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
16
src/r_defs.h
16
src/r_defs.h
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue