diff --git a/src/actor.h b/src/actor.h index 4deb349a78..96e4248632 100644 --- a/src/actor.h +++ b/src/actor.h @@ -1360,6 +1360,14 @@ inline T *Spawn (const fixedvec3 &pos, replace_t allowreplacement) return static_cast(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 diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index a99ef93239..65d9d08b4d 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -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; } diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 79dd6253f7..85335587e7 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -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; diff --git a/src/g_doom/a_fatso.cpp b/src/g_doom/a_fatso.cpp index 066e60468c..c9f53d9d3e 100644 --- a/src/g_doom/a_fatso.cpp +++ b/src/g_doom/a_fatso.cpp @@ -145,7 +145,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Mushroom) P_CheckSplash(self, 128<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 diff --git a/src/g_doom/a_lostsoul.cpp b/src/g_doom/a_lostsoul.cpp index 1182292e00..7dc9a1b8f9 100644 --- a/src/g_doom/a_lostsoul.cpp +++ b/src/g_doom/a_lostsoul.cpp @@ -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) diff --git a/src/g_doom/a_painelemental.cpp b/src/g_doom/a_painelemental.cpp index f361fb78d0..cb5205a762 100644 --- a/src/g_doom/a_painelemental.cpp +++ b/src/g_doom/a_painelemental.cpp @@ -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); diff --git a/src/g_heretic/a_dsparil.cpp b/src/g_heretic/a_dsparil.cpp index e4d86c83af..b12be80810 100644 --- a/src/g_heretic/a_dsparil.cpp +++ b/src/g_heretic/a_dsparil.cpp @@ -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 (self->x, self->y, self->z, ALLOW_REPLACE); + Spawn (self->X(), self->Y(), self->Z(), ALLOW_REPLACE); } } } diff --git a/src/r_defs.h b/src/r_defs.h index dd8496e4d9..4f0b5ed01c 100644 --- a/src/r_defs.h +++ b/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