- Random spawners no longer move the missile forward when spawning them, because presumably

whatever spawned the random spawner already took care of this.
- Added a maxdist parameter to P_CheckMissileSpawn() to help ensure that it doesn't completely 
  move the spawned missile outside of its shooter (and potentially beyond a wall the shooter
  might happen to be standing next to).

SVN r4194 (trunk)
This commit is contained in:
Randy Heit 2013-03-21 03:06:04 +00:00
parent 34b2d0b21a
commit 2874d927b1
15 changed files with 79 additions and 91 deletions

View file

@ -4256,7 +4256,7 @@ void FParser::SF_SpawnShot2(void)
S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_NORM); S_Sound (mo, CHAN_VOICE, mo->SeeSound, 1, ATTN_NORM);
mo->target = source; mo->target = source;
P_ThrustMobj(mo, mo->angle = source->angle, mo->Speed); P_ThrustMobj(mo, mo->angle = source->angle, mo->Speed);
if (!P_CheckMissileSpawn(mo)) mo = NULL; if (!P_CheckMissileSpawn(mo, source->radius)) mo = NULL;
} }
t_return.value.mobj = mo; t_return.value.mobj = mo;
} }

View file

@ -175,7 +175,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcanoBlast)
blast->vely = FixedMul (1*FRACUNIT, finesine[angle]); blast->vely = FixedMul (1*FRACUNIT, finesine[angle]);
blast->velz = (FRACUNIT*5/2) + (pr_blast() << 10); blast->velz = (FRACUNIT*5/2) + (pr_blast() << 10);
S_Sound (blast, CHAN_BODY, "world/volcano/shoot", 1, ATTN_NORM); S_Sound (blast, CHAN_BODY, "world/volcano/shoot", 1, ATTN_NORM);
P_CheckMissileSpawn (blast); P_CheckMissileSpawn (blast, self->radius);
} }
} }
@ -209,7 +209,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_VolcBallImpact)
tiny->velx = FixedMul (FRACUNIT*7/10, finecosine[angle]); tiny->velx = FixedMul (FRACUNIT*7/10, finecosine[angle]);
tiny->vely = FixedMul (FRACUNIT*7/10, finesine[angle]); tiny->vely = FixedMul (FRACUNIT*7/10, finesine[angle]);
tiny->velz = FRACUNIT + (pr_volcimpact() << 9); tiny->velz = FRACUNIT + (pr_volcimpact() << 9);
P_CheckMissileSpawn (tiny); P_CheckMissileSpawn (tiny, self->radius);
} }
} }

View file

@ -395,7 +395,7 @@ void FireMacePL1B (AActor *actor)
ball->velx = (actor->velx>>1) + FixedMul(ball->Speed, finecosine[angle]); ball->velx = (actor->velx>>1) + FixedMul(ball->Speed, finecosine[angle]);
ball->vely = (actor->vely>>1) + FixedMul(ball->Speed, finesine[angle]); ball->vely = (actor->vely>>1) + FixedMul(ball->Speed, finesine[angle]);
S_Sound (ball, CHAN_BODY, "weapons/maceshoot", 1, ATTN_NORM); S_Sound (ball, CHAN_BODY, "weapons/maceshoot", 1, ATTN_NORM);
P_CheckMissileSpawn (ball); P_CheckMissileSpawn (ball, actor->radius);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -538,7 +538,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2)
tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]); tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]);
tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]); tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]);
tiny->velz = self->velz; tiny->velz = self->velz;
P_CheckMissileSpawn (tiny); P_CheckMissileSpawn (tiny, self->radius);
tiny = Spawn("MaceFX3", self->x, self->y, self->z, ALLOW_REPLACE); tiny = Spawn("MaceFX3", self->x, self->y, self->z, ALLOW_REPLACE);
angle = self->angle-ANG90; angle = self->angle-ANG90;
@ -548,7 +548,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MaceBallImpact2)
tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]); tiny->velx = (self->velx>>1) + FixedMul(self->velz-FRACUNIT, finecosine[angle]);
tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]); tiny->vely = (self->vely>>1) + FixedMul(self->velz-FRACUNIT, finesine[angle]);
tiny->velz = self->velz; tiny->velz = self->velz;
P_CheckMissileSpawn (tiny); P_CheckMissileSpawn (tiny, self->radius);
} }
else else
{ // Explode { // Explode
@ -809,7 +809,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers)
angle >>= ANGLETOFINESHIFT; angle >>= ANGLETOFINESHIFT;
ripper->velx = FixedMul (ripper->Speed, finecosine[angle]); ripper->velx = FixedMul (ripper->Speed, finecosine[angle]);
ripper->vely = FixedMul (ripper->Speed, finesine[angle]); ripper->vely = FixedMul (ripper->Speed, finesine[angle]);
P_CheckMissileSpawn (ripper); P_CheckMissileSpawn (ripper, self->radius);
} }
} }
@ -1064,7 +1064,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SkullRodStorm)
mo->velx = 1; // Force collision detection mo->velx = 1; // Force collision detection
mo->velz = -mo->Speed; mo->velz = -mo->Speed;
mo->special2 = self->special2; // Transfer player number mo->special2 = self->special2; // Transfer player number
P_CheckMissileSpawn (mo); P_CheckMissileSpawn (mo, self->radius);
if (self->special1 != -1 && !S_IsActorPlayingSomething (self, CHAN_BODY, -1)) if (self->special1 != -1 && !S_IsActorPlayingSomething (self, CHAN_BODY, -1))
{ {
S_Sound (self, CHAN_BODY|CHAN_LOOP, self->special1, 1, ATTN_NORM); S_Sound (self, CHAN_BODY|CHAN_LOOP, self->special1, 1, ATTN_NORM);
@ -1314,7 +1314,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2)
{ {
S_Sound (self, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM); S_Sound (self, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
} }
P_CheckMissileSpawn (mo); P_CheckMissileSpawn (mo, self->radius);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View file

@ -116,7 +116,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichAttack)
fire->velz = baseFire->velz; fire->velz = baseFire->velz;
fire->Damage = 0; fire->Damage = 0;
fire->health = (i+1) * 2; fire->health = (i+1) * 2;
P_CheckMissileSpawn (fire); P_CheckMissileSpawn (fire, self->radius);
} }
} }
} }
@ -185,7 +185,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_LichIceImpact)
shard->velx = FixedMul (shard->Speed, finecosine[angle]); shard->velx = FixedMul (shard->Speed, finecosine[angle]);
shard->vely = FixedMul (shard->Speed, finesine[angle]); shard->vely = FixedMul (shard->Speed, finesine[angle]);
shard->velz = -FRACUNIT*6/10; shard->velz = -FRACUNIT*6/10;
P_CheckMissileSpawn (shard); P_CheckMissileSpawn (shard, self->radius);
} }
} }

View file

@ -137,7 +137,7 @@ bool AArtiPoisonBag3::Use (bool pickup)
mo->target = Owner; mo->target = Owner;
mo->tics -= pr_poisonbag()&3; mo->tics -= pr_poisonbag()&3;
P_CheckMissileSpawn(mo); P_CheckMissileSpawn(mo, Owner->radius);
return true; return true;
} }
return false; return false;

View file

@ -502,5 +502,5 @@ AActor *P_SpawnKoraxMissile (fixed_t x, fixed_t y, fixed_t z,
dist = 1; dist = 1;
} }
th->velz = (dest->z-z+(30*FRACUNIT))/dist; th->velz = (dest->z-z+(30*FRACUNIT))/dist;
return (P_CheckMissileSpawn(th) ? th : NULL); return (P_CheckMissileSpawn(th, source->radius) ? th : NULL);
} }

View file

@ -375,7 +375,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_MntrFloorFire)
mo = Spawn("MinotaurFX3", x, y, self->floorz, ALLOW_REPLACE); mo = Spawn("MinotaurFX3", x, y, self->floorz, ALLOW_REPLACE);
mo->target = self->target; mo->target = self->target;
mo->velx = 1; // Force block checking mo->velx = 1; // Force block checking
P_CheckMissileSpawn (mo); P_CheckMissileSpawn (mo, self->radius);
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View file

@ -173,7 +173,7 @@ class ARandomSpawner : public AActor
newmobj->z += SpawnPoint[2]; newmobj->z += SpawnPoint[2];
} }
if (newmobj->flags & MF_MISSILE) if (newmobj->flags & MF_MISSILE)
P_CheckMissileSpawn(newmobj); P_CheckMissileSpawn(newmobj, 0);
// Bouncecount is used to count how many recursions we're in. // Bouncecount is used to count how many recursions we're in.
if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner"))) if (newmobj->IsKindOf(PClass::FindClass("RandomSpawner")))
newmobj->bouncecount = ++bouncecount; newmobj->bouncecount = ++bouncecount;

View file

@ -29,7 +29,7 @@ void A_SpectralMissile (AActor *self, const char *missilename)
if (missile != NULL) if (missile != NULL)
{ {
missile->tracer = self->target; missile->tracer = self->target;
P_CheckMissileSpawn(missile); P_CheckMissileSpawn(missile, self->radius);
} }
} }
} }

View file

@ -64,7 +64,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_SentinelAttack)
trail->velx = missile->velx; trail->velx = missile->velx;
trail->vely = missile->vely; trail->vely = missile->vely;
trail->velz = missile->velz; trail->velz = missile->velz;
P_CheckMissileSpawn (trail); P_CheckMissileSpawn (trail, self->radius);
} }
} }
missile->z += missile->velz >> 2; missile->z += missile->velz >> 2;

View file

@ -538,7 +538,7 @@ AActor *P_SpawnSubMissile (AActor *source, const PClass *type, AActor *target)
} }
} }
if (P_CheckMissileSpawn (other)) if (P_CheckMissileSpawn (other, source->radius))
{ {
angle_t pitch = P_AimLineAttack (source, source->angle, 1024*FRACUNIT); angle_t pitch = P_AimLineAttack (source, source->angle, 1024*FRACUNIT);
other->velz = FixedMul (-finesine[pitch>>ANGLETOFINESHIFT], other->Speed); other->velz = FixedMul (-finesine[pitch>>ANGLETOFINESHIFT], other->Speed);

View file

@ -481,7 +481,7 @@ enum // P_RailAttack / A_RailAttack / A_CustomRailgun / P_DrawRailTrail flags
}; };
bool P_CheckMissileSpawn (AActor *missile); bool P_CheckMissileSpawn (AActor *missile, fixed_t maxdist);
void P_PlaySpawnSound(AActor *missile, AActor *spawner); void P_PlaySpawnSound(AActor *missile, AActor *spawner);
// [RH] Position the chasecam // [RH] Position the chasecam

View file

@ -5258,10 +5258,8 @@ void P_CheckSplash(AActor *self, fixed_t distance)
// //
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
bool P_CheckMissileSpawn (AActor* th) bool P_CheckMissileSpawn (AActor* th, fixed_t maxdist)
{ {
int shift, count = 1;
// [RH] Don't decrement tics if they are already less than 1 // [RH] Don't decrement tics if they are already less than 1
if ((th->flags4 & MF4_RANDOMIZE) && th->tics > 0) if ((th->flags4 & MF4_RANDOMIZE) && th->tics > 0)
{ {
@ -5270,76 +5268,66 @@ bool P_CheckMissileSpawn (AActor* th)
th->tics = 1; th->tics = 1;
} }
// move a little forward so an angle can be computed if it immediately explodes if (maxdist > 0)
if (th->Speed >= 100*FRACUNIT)
{ // Ultra-fast ripper spawning missile
shift = 3;
}
else
{ // Normal missile
shift = 1;
}
if (th->radius > 0)
{ {
while ( ((th->velx >> shift) > th->radius) || ((th->vely >> shift) > th->radius)) // move a little forward so an angle can be computed if it immediately explodes
TVector3<double> advance(FIXED2DBL(th->velx), FIXED2DBL(th->vely), FIXED2DBL(th->velz));
double maxsquared = FIXED2DBL(maxdist);
maxsquared *= maxsquared;
// Keep halving the advance vector until we get something less than maxdist
// units away, since we still want to spawn the missile inside the shooter.
while (TVector2<double>(advance).LengthSquared() >= maxsquared)
{ {
// we need to take smaller steps but to produce the same end result advance *= 0.5f;
// we have to do more of them.
shift++;
count<<=1;
} }
th->x += FLOAT2FIXED(advance.X);
th->y += FLOAT2FIXED(advance.Y);
th->z += FLOAT2FIXED(advance.Z);
} }
FCheckPosition tm(!!(th->flags2 & MF2_RIP)); FCheckPosition tm(!!(th->flags2 & MF2_RIP));
for(int i=0; i<count; i++) // killough 8/12/98: for non-missile objects (e.g. grenades)
//
// [GZ] MBF excludes non-missile objects from the P_TryMove test
// and subsequent potential P_ExplodeMissile call. That is because
// in MBF, a projectile is not an actor with the MF_MISSILE flag
// but an actor with either or both the MF_MISSILE and MF_BOUNCES
// flags, and a grenade is identified by not having MF_MISSILE.
// Killough wanted grenades not to explode directly when spawned,
// therefore they can be fired safely even when humping a wall as
// they will then just drop on the floor at their shooter's feet.
//
// However, ZDoom does allow non-missiles to be shot as well, so
// Killough's check for non-missiles is inadequate here. So let's
// replace it by a check for non-missile and MBF bounce type.
// This should allow MBF behavior where relevant without altering
// established ZDoom behavior for crazy stuff like a cacodemon cannon.
bool MBFGrenade = (!(th->flags & MF_MISSILE) || (th->BounceFlags & BOUNCE_MBF));
// killough 3/15/98: no dropoff (really = don't care for missiles)
if (!(P_TryMove (th, th->x, th->y, false, NULL, tm, true)))
{ {
th->x += th->velx >> shift; // [RH] Don't explode ripping missiles that spawn inside something
th->y += th->vely >> shift; if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP))
th->z += th->velz >> shift;
// killough 8/12/98: for non-missile objects (e.g. grenades)
//
// [GZ] MBF excludes non-missile objects from the P_TryMove test
// and subsequent potential P_ExplodeMissile call. That is because
// in MBF, a projectile is not an actor with the MF_MISSILE flag
// but an actor with either or both the MF_MISSILE and MF_BOUNCES
// flags, and a grenade is identified by not having MF_MISSILE.
// Killough wanted grenades not to explode directly when spawned,
// therefore they can be fired safely even when humping a wall as
// they will then just drop on the floor at their shooter's feet.
//
// However, ZDoom does allow non-missiles to be shot as well, so
// Killough's check for non-missiles is inadequate here. So let's
// replace it by a check for non-missile and MBF bounce type.
// This should allow MBF behavior where relevant without altering
// established ZDoom behavior for crazy stuff like a cacodemon cannon.
bool MBFGrenade = (!(th->flags & MF_MISSILE) || (th->BounceFlags & BOUNCE_MBF));
// killough 3/15/98: no dropoff (really = don't care for missiles)
if (!(P_TryMove (th, th->x, th->y, false, NULL, tm, true)))
{ {
// [RH] Don't explode ripping missiles that spawn inside something // If this is a monster spawned by A_CustomMissile subtract it from the counter.
if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP)) th->ClearCounters();
// [RH] Don't explode missiles that spawn on top of horizon lines
if (th->BlockingLine != NULL && th->BlockingLine->special == Line_Horizon)
{ {
// If this is a monster spawned by A_CustomMissile subtract it from the counter. th->Destroy ();
th->ClearCounters();
// [RH] Don't explode missiles that spawn on top of horizon lines
if (th->BlockingLine != NULL && th->BlockingLine->special == Line_Horizon)
{
th->Destroy ();
}
else if (MBFGrenade && th->BlockingLine != NULL )
{
P_BounceWall(th);
}
else
{
P_ExplodeMissile (th, NULL, th->BlockingMobj);
}
return false;
} }
else if (MBFGrenade && th->BlockingLine != NULL)
{
P_BounceWall(th);
}
else
{
P_ExplodeMissile (th, NULL, th->BlockingMobj);
}
return false;
} }
} }
return true; return true;
@ -5473,7 +5461,7 @@ AActor *P_SpawnMissileXYZ (fixed_t x, fixed_t y, fixed_t z,
th->SetFriendPlayer(owner->player); th->SetFriendPlayer(owner->player);
} }
return (!checkspawn || P_CheckMissileSpawn (th)) ? th : NULL; return (!checkspawn || P_CheckMissileSpawn (th, source->radius)) ? th : NULL;
} }
AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const PClass *type) AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const PClass *type)
@ -5503,7 +5491,7 @@ AActor * P_OldSpawnMissile(AActor * source, AActor * owner, AActor * dest, const
th->SetFriendPlayer(owner->player); th->SetFriendPlayer(owner->player);
} }
P_CheckMissileSpawn(th); P_CheckMissileSpawn(th, source->radius);
return th; return th;
} }
@ -5592,7 +5580,7 @@ AActor *P_SpawnMissileAngleZSpeed (AActor *source, fixed_t z,
mo->SetFriendPlayer(owner->player); mo->SetFriendPlayer(owner->player);
} }
return (!checkspawn || P_CheckMissileSpawn(mo)) ? mo : NULL; return (!checkspawn || P_CheckMissileSpawn(mo, source->radius)) ? mo : NULL;
} }
/* /*
@ -5711,7 +5699,7 @@ AActor *P_SpawnPlayerMissile (AActor *source, fixed_t x, fixed_t y, fixed_t z,
{ {
MissileActor->SetFriendPlayer(source->player); MissileActor->SetFriendPlayer(source->player);
} }
if (P_CheckMissileSpawn (MissileActor)) if (P_CheckMissileSpawn (MissileActor, source->radius))
{ {
return MissileActor; return MissileActor;
} }

View file

@ -336,7 +336,7 @@ nolead: mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y);
} }
if (mobj->flags & MF_MISSILE) if (mobj->flags & MF_MISSILE)
{ {
if (P_CheckMissileSpawn (mobj)) if (P_CheckMissileSpawn (mobj, source->radius))
{ {
rtn = true; rtn = true;
} }

View file

@ -333,7 +333,7 @@ static void DoAttack (AActor *self, bool domelee, bool domissile,
{ {
missile->tracer=self->target; missile->tracer=self->target;
} }
P_CheckMissileSpawn(missile); P_CheckMissileSpawn(missile, self->radius);
} }
} }
} }
@ -1019,7 +1019,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomMissile)
missile->FriendPlayer = 0; missile->FriendPlayer = 0;
} }
} }
P_CheckMissileSpawn(missile); P_CheckMissileSpawn(missile, self->radius);
} }
} }
} }
@ -1170,7 +1170,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_CustomComboAttack)
{ {
missile->tracer=self->target; missile->tracer=self->target;
} }
P_CheckMissileSpawn(missile); P_CheckMissileSpawn(missile, self->radius);
} }
} }
} }
@ -2045,8 +2045,8 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_ThrowGrenade)
bo->vely = xy_vely + z_vely + (self->vely >> 1); bo->vely = xy_vely + z_vely + (self->vely >> 1);
bo->velz = xy_velz + z_velz; bo->velz = xy_velz + z_velz;
bo->target= self; bo->target = self;
P_CheckMissileSpawn (bo); P_CheckMissileSpawn (bo, self->radius);
} }
else ACTION_SET_RESULT(false); else ACTION_SET_RESULT(false);
} }