- Fixed: Argument count for UsePuzzleItem was wrong.
- Added more things from Gez's experimental build: * MBF grenade and bouncing code. * Arch Vile ghosts emulation (only for compatibility.txt.) * Several MBF related compatibility options. SVN r1821 (trunk)
This commit is contained in:
parent
238d4c3fac
commit
ea8c94d637
24 changed files with 367 additions and 160 deletions
245
src/p_mobj.cpp
245
src/p_mobj.cpp
|
|
@ -1013,24 +1013,42 @@ void AActor::Touch (AActor *toucher)
|
|||
bool AActor::Grind(bool items)
|
||||
{
|
||||
// crunch bodies to giblets
|
||||
if ((this->flags & MF_CORPSE) &&
|
||||
!(this->flags3 & MF3_DONTGIB) &&
|
||||
(this->health <= 0))
|
||||
if ((flags & MF_CORPSE) && !(flags3 & MF3_DONTGIB) && (health <= 0))
|
||||
{
|
||||
FState * state = this->FindState(NAME_Crush);
|
||||
if (state != NULL && !(this->flags & MF_ICECORPSE))
|
||||
FState * state = FindState(NAME_Crush);
|
||||
bool isgeneric = false;
|
||||
// ZDoom behavior differs from standard as crushed corpses cannot be raised.
|
||||
// The reason for the change was originally because of a problem with players,
|
||||
// see rh_log entry for February 21, 1999. Don't know if it is still relevant.
|
||||
if (state == NULL // Only use the default crushed state if:
|
||||
&& !(flags & MF_NOBLOOD) // 1. the monster bleeeds,
|
||||
&& (i_compatflags & COMPATF_CORPSEGIBS) // 2. the compat setting is on,
|
||||
&& player != NULL) // 3. and the thing isn't a player.
|
||||
{
|
||||
isgeneric = true;
|
||||
state = FindState(NAME_GenericCrush);
|
||||
if (state != NULL && (sprites[state->sprite].numframes <= 0))
|
||||
state = NULL; // If one of these tests fails, do not use that state.
|
||||
}
|
||||
if (state != NULL && !(flags & MF_ICECORPSE))
|
||||
{
|
||||
if (this->flags4 & MF4_BOSSDEATH)
|
||||
{
|
||||
CALL_ACTION(A_BossDeath, this);
|
||||
}
|
||||
this->flags &= ~MF_SOLID;
|
||||
this->flags3 |= MF3_DONTGIB;
|
||||
this->height = this->radius = 0;
|
||||
this->SetState (state);
|
||||
flags &= ~MF_SOLID;
|
||||
flags3 |= MF3_DONTGIB;
|
||||
height = radius = 0;
|
||||
SetState (state);
|
||||
if (isgeneric) // Not a custom crush state, so colorize it appropriately.
|
||||
{
|
||||
S_Sound (this, CHAN_BODY, "misc/fallingsplat", 1, ATTN_IDLE);
|
||||
PalEntry bloodcolor = PalEntry(GetClass()->Meta.GetMetaInt(AMETA_BloodColor));
|
||||
if (bloodcolor!=0) Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!(this->flags & MF_NOBLOOD))
|
||||
if (!(flags & MF_NOBLOOD))
|
||||
{
|
||||
if (this->flags4 & MF4_BOSSDEATH)
|
||||
{
|
||||
|
|
@ -1053,17 +1071,17 @@ bool AActor::Grind(bool items)
|
|||
if (i == NULL)
|
||||
{
|
||||
// if there's no gib sprite don't crunch it.
|
||||
this->flags &= ~MF_SOLID;
|
||||
this->flags3 |= MF3_DONTGIB;
|
||||
this->height = this->radius = 0;
|
||||
flags &= ~MF_SOLID;
|
||||
flags3 |= MF3_DONTGIB;
|
||||
height = radius = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
AActor *gib = Spawn (i, this->x, this->y, this->z, ALLOW_REPLACE);
|
||||
AActor *gib = Spawn (i, x, y, z, ALLOW_REPLACE);
|
||||
if (gib != NULL)
|
||||
{
|
||||
gib->RenderStyle = this->RenderStyle;
|
||||
gib->alpha = this->alpha;
|
||||
gib->RenderStyle = RenderStyle;
|
||||
gib->alpha = alpha;
|
||||
gib->height = 0;
|
||||
gib->radius = 0;
|
||||
}
|
||||
|
|
@ -1072,37 +1090,45 @@ bool AActor::Grind(bool items)
|
|||
PalEntry bloodcolor = (PalEntry)this->GetClass()->Meta.GetMetaInt(AMETA_BloodColor);
|
||||
if (bloodcolor!=0) gib->Translation = TRANSLATION(TRANSLATION_Blood, bloodcolor.a);
|
||||
}
|
||||
if (this->flags & MF_ICECORPSE)
|
||||
if (flags & MF_ICECORPSE)
|
||||
{
|
||||
this->tics = 1;
|
||||
this->velx = this->vely = this->velz = 0;
|
||||
tics = 1;
|
||||
velx = vely = velz = 0;
|
||||
}
|
||||
else if (this->player)
|
||||
else if (player)
|
||||
{
|
||||
this->flags |= MF_NOCLIP;
|
||||
this->flags3 |= MF3_DONTGIB;
|
||||
this->renderflags |= RF_INVISIBLE;
|
||||
flags |= MF_NOCLIP;
|
||||
flags3 |= MF3_DONTGIB;
|
||||
renderflags |= RF_INVISIBLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Destroy ();
|
||||
Destroy ();
|
||||
}
|
||||
return false; // keep checking
|
||||
}
|
||||
|
||||
// crunch dropped items
|
||||
if (this->flags & MF_DROPPED)
|
||||
if (flags & MF_DROPPED)
|
||||
{
|
||||
if (items) this->Destroy (); // Only destroy dropped items if wanted
|
||||
if (items) Destroy (); // Only destroy dropped items if wanted
|
||||
return false; // keep checking
|
||||
}
|
||||
|
||||
if (!(this->flags & MF_SOLID) || (this->flags & MF_NOCLIP))
|
||||
// killough 11/98: kill touchy things immediately
|
||||
if (flags6 & MF6_TOUCHY && (flags6 & MF6_ARMED || IsSentient()))
|
||||
{
|
||||
flags6 &= ~MF6_ARMED; // Disarm
|
||||
P_DamageMobj (this, NULL, NULL, health, NAME_Crush, DMG_FORCED); // kill object
|
||||
return true; // keep checking
|
||||
}
|
||||
|
||||
if (!(flags & MF_SOLID) || (flags & MF_NOCLIP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(this->flags & MF_SHOOTABLE))
|
||||
if (!(flags & MF_SHOOTABLE))
|
||||
{
|
||||
return false; // assume it is bloody gibs or something
|
||||
}
|
||||
|
|
@ -1324,7 +1350,10 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
|
|||
// Landed in some sort of liquid
|
||||
if (BounceFlags & BOUNCE_ExplodeOnWater)
|
||||
{
|
||||
P_ExplodeMissile(this, NULL, NULL);
|
||||
if (flags & MF_MISSILE)
|
||||
P_ExplodeMissile(this, NULL, NULL);
|
||||
else
|
||||
Die(NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
if (!(BounceFlags & BOUNCE_CanBounceWater))
|
||||
|
|
@ -1348,37 +1377,49 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
|
|||
// The amount of bounces is limited
|
||||
if (bouncecount>0 && --bouncecount==0)
|
||||
{
|
||||
P_ExplodeMissile(this, NULL, NULL);
|
||||
if (flags & MF_MISSILE)
|
||||
P_ExplodeMissile(this, NULL, NULL);
|
||||
else
|
||||
Die(NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
fixed_t dot = TMulScale16 (velx, plane.a, vely, plane.b, velz, plane.c);
|
||||
|
||||
if (BounceFlags & BOUNCE_HereticType)
|
||||
if (BounceFlags & (BOUNCE_HereticType | BOUNCE_MBF))
|
||||
{
|
||||
velx -= MulScale15 (plane.a, dot);
|
||||
vely -= MulScale15 (plane.b, dot);
|
||||
velz -= MulScale15 (plane.c, dot);
|
||||
angle = R_PointToAngle2 (0, 0, velx, vely);
|
||||
flags |= MF_INBOUNCE;
|
||||
SetState (FindState(NAME_Death));
|
||||
flags &= ~MF_INBOUNCE;
|
||||
return false;
|
||||
if (!(BounceFlags & BOUNCE_MBF)) // Heretic projectiles die, MBF projectiles don't.
|
||||
{
|
||||
flags |= MF_INBOUNCE;
|
||||
SetState (FindState(NAME_Death));
|
||||
flags &= ~MF_INBOUNCE;
|
||||
return false;
|
||||
}
|
||||
else velz = FixedMul(velz, bouncefactor);
|
||||
}
|
||||
else // Don't run through this for MBF-style bounces
|
||||
{
|
||||
// The reflected velocity keeps only about 70% of its original speed
|
||||
velx = FixedMul (velx - MulScale15 (plane.a, dot), bouncefactor);
|
||||
vely = FixedMul (vely - MulScale15 (plane.b, dot), bouncefactor);
|
||||
velz = FixedMul (velz - MulScale15 (plane.c, dot), bouncefactor);
|
||||
angle = R_PointToAngle2 (0, 0, velx, vely);
|
||||
}
|
||||
|
||||
// The reflected velocity keeps only about 70% of its original speed
|
||||
velx = FixedMul (velx - MulScale15 (plane.a, dot), bouncefactor);
|
||||
vely = FixedMul (vely - MulScale15 (plane.b, dot), bouncefactor);
|
||||
velz = FixedMul (velz - MulScale15 (plane.c, dot), bouncefactor);
|
||||
angle = R_PointToAngle2 (0, 0, velx, vely);
|
||||
|
||||
PlayBounceSound(true);
|
||||
if (BounceFlags & BOUNCE_AutoOff)
|
||||
if (BounceFlags & BOUNCE_MBF) // Bring it to rest below a certain speed
|
||||
{
|
||||
if (abs(velz) < (fixed_t)(Mass * GetGravity() / 64))
|
||||
velz = 0;
|
||||
}
|
||||
else if (BounceFlags & BOUNCE_AutoOff)
|
||||
{
|
||||
if (!(flags & MF_NOGRAVITY) && (velz < 3*FRACUNIT))
|
||||
{
|
||||
BounceFlags &= ~BOUNCE_TypeMask;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1723,13 +1764,20 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
if (!P_TryMove (mo, ptryx, ptryy, true, walkplane, tm))
|
||||
{
|
||||
// blocked move
|
||||
AActor *BlockingMobj = mo->BlockingMobj;
|
||||
line_t *BlockingLine = mo->BlockingLine;
|
||||
|
||||
if ((mo->flags2 & (MF2_SLIDE|MF2_BLASTED) || bForceSlide) && !(mo->flags&MF_MISSILE))
|
||||
if (!(mo->flags & MF_MISSILE) && (mo->BounceFlags & BOUNCE_MBF)
|
||||
&& (BlockingMobj != NULL ? P_BounceActor(mo, BlockingMobj) : P_BounceWall(mo)))
|
||||
{
|
||||
// try to slide along it
|
||||
if (mo->BlockingMobj == NULL)
|
||||
// Do nothing, relevant actions already done in the condition.
|
||||
// This allows to avoid setting velocities to 0 in the final else of this series.
|
||||
}
|
||||
else if ((mo->flags2 & (MF2_SLIDE|MF2_BLASTED) || bForceSlide) && !(mo->flags&MF_MISSILE))
|
||||
{ // try to slide along it
|
||||
if (BlockingMobj == NULL)
|
||||
{ // slide against wall
|
||||
if (mo->BlockingLine != NULL &&
|
||||
if (BlockingLine != NULL &&
|
||||
mo->player && mo->waterlevel && mo->waterlevel < 3 &&
|
||||
(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove) &&
|
||||
mo->BlockingLine->sidedef[1] != NULL)
|
||||
|
|
@ -1800,36 +1848,17 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
}
|
||||
else if (mo->flags & MF_MISSILE)
|
||||
{
|
||||
AActor *BlockingMobj = mo->BlockingMobj;
|
||||
steps = 0;
|
||||
if (BlockingMobj)
|
||||
{
|
||||
if (mo->BounceFlags & BOUNCE_Actors)
|
||||
{
|
||||
if ((mo->BounceFlags & BOUNCE_AllActors) ||
|
||||
(BlockingMobj->flags2 & MF2_REFLECTIVE) ||
|
||||
((!BlockingMobj->player) &&
|
||||
(!(BlockingMobj->flags3 & MF3_ISMONSTER))))
|
||||
{
|
||||
fixed_t speed;
|
||||
|
||||
angle = R_PointToAngle2 (BlockingMobj->x,
|
||||
BlockingMobj->y, mo->x, mo->y)
|
||||
+ANGLE_1*((pr_bounce()%16)-8);
|
||||
speed = P_AproxDistance (mo->velx, mo->vely);
|
||||
speed = FixedMul (speed, (fixed_t)(0.75*FRACUNIT));
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul (speed, finecosine[angle]);
|
||||
mo->vely = FixedMul (speed, finesine[angle]);
|
||||
mo->PlayBounceSound(true);
|
||||
return oldfloorz;
|
||||
}
|
||||
else
|
||||
{ // Struck a player/creature
|
||||
// Bounce test and code moved to P_BounceActor
|
||||
if (!P_BounceActor(mo, BlockingMobj))
|
||||
{ // Struck a player/creature
|
||||
P_ExplodeMissile (mo, NULL, BlockingMobj);
|
||||
return oldfloorz;
|
||||
}
|
||||
return oldfloorz;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1841,12 +1870,9 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
|
|||
return oldfloorz;
|
||||
}
|
||||
}
|
||||
if (BlockingMobj &&
|
||||
(BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
if (BlockingMobj && (BlockingMobj->flags2 & MF2_REFLECTIVE))
|
||||
{
|
||||
angle = R_PointToAngle2(BlockingMobj->x,
|
||||
BlockingMobj->y,
|
||||
mo->x, mo->y);
|
||||
angle = R_PointToAngle2(BlockingMobj->x, BlockingMobj->y, mo->x, mo->y);
|
||||
|
||||
// Change angle for deflection/reflection
|
||||
if (mo->AdjustReflectionAngle (BlockingMobj, angle))
|
||||
|
|
@ -1947,10 +1973,12 @@ explode:
|
|||
return oldfloorz;
|
||||
}
|
||||
|
||||
if (mo->flags & MF_CORPSE)
|
||||
// killough 8/11/98: add bouncers
|
||||
// killough 9/15/98: add objects falling off ledges
|
||||
// killough 11/98: only include bouncers hanging off ledges
|
||||
if ((mo->flags & MF_CORPSE) || (mo->BounceFlags & BOUNCE_MBF && mo->z > mo->dropoffz) || (mo->flags6 & MF6_FALLING))
|
||||
{ // Don't stop sliding if halfway off a step with some velocity
|
||||
if (mo->velx > FRACUNIT/4 || mo->velx < -FRACUNIT/4
|
||||
|| mo->vely > FRACUNIT/4 || mo->vely < -FRACUNIT/4)
|
||||
if (mo->velx > FRACUNIT/4 || mo->velx < -FRACUNIT/4 || mo->vely > FRACUNIT/4 || mo->vely < -FRACUNIT/4)
|
||||
{
|
||||
if (mo->floorz > mo->Sector->floorplane.ZatPoint (mo->x, mo->y))
|
||||
{
|
||||
|
|
@ -2170,7 +2198,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
if (mo->BounceFlags & BOUNCE_Floors)
|
||||
{
|
||||
mo->FloorBounceMissile (mo->floorsector->floorplane);
|
||||
return;
|
||||
/* if (!(mo->flags6 & MF6_CANJUMP)) */ return;
|
||||
}
|
||||
else if (mo->flags3 & MF3_NOEXPLODEFLOOR)
|
||||
{
|
||||
|
|
@ -2196,6 +2224,10 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (mo->BounceFlags & BOUNCE_MBF && mo->velz) // check for MBF-like bounce on non-missiles
|
||||
{
|
||||
mo->FloorBounceMissile(mo->floorsector->floorplane);
|
||||
}
|
||||
if (mo->flags3 & MF3_ISMONSTER) // Blasted mobj falling
|
||||
{
|
||||
if (mo->velz < -(23*FRACUNIT))
|
||||
|
|
@ -2263,7 +2295,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
|
|||
if (mo->BounceFlags & BOUNCE_Ceilings)
|
||||
{ // ceiling bounce
|
||||
mo->FloorBounceMissile (mo->ceilingsector->ceilingplane);
|
||||
return;
|
||||
/*if (!(mo->flags6 & MF6_CANJUMP))*/ return;
|
||||
}
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{ // the skull slammed into something
|
||||
|
|
@ -3157,11 +3189,18 @@ void AActor::Tick ()
|
|||
{ // actor was destroyed
|
||||
return;
|
||||
}
|
||||
if ((velx | vely) == 0 && (flags2 & MF2_BLASTED))
|
||||
{ // Reset to not blasted when velocitiess are gone
|
||||
flags2 &= ~MF2_BLASTED;
|
||||
}
|
||||
if ((velx | vely) == 0) // Actors at rest
|
||||
{
|
||||
if (flags2 & MF2_BLASTED)
|
||||
{ // Reset to not blasted when velocities are gone
|
||||
flags2 &= ~MF2_BLASTED;
|
||||
}
|
||||
if ((flags6 & MF6_TOUCHY) && !IsSentient())
|
||||
{ // Arm a mine which has come to rest
|
||||
flags6 |= MF6_ARMED;
|
||||
}
|
||||
|
||||
}
|
||||
if (flags2 & MF2_FLOATBOB)
|
||||
{ // Floating item bobbing motion
|
||||
z += FloatBobDiffs[(FloatBobPhase + level.maptime) & 63];
|
||||
|
|
@ -4685,6 +4724,15 @@ bool P_HitFloor (AActor *thing)
|
|||
{
|
||||
const msecnode_t *m;
|
||||
|
||||
// killough 11/98: touchy objects explode on impact
|
||||
// Allow very short drops to be safe, so that a touchy can be summoned without exploding.
|
||||
if (thing->flags6 & MF6_TOUCHY && ((thing->flags6 & MF6_ARMED) || thing->IsSentient()) && ((thing->velz) < (-5 * FRACUNIT)))
|
||||
{
|
||||
thing->flags6 &= ~MF6_ARMED; // Disarm
|
||||
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_Crush, DMG_FORCED); // kill object
|
||||
return true;
|
||||
}
|
||||
|
||||
if (thing->flags2 & MF2_FLOATBOB || thing->flags3 & MF3_DONTSPLASH)
|
||||
return false;
|
||||
|
||||
|
|
@ -4770,9 +4818,26 @@ bool P_CheckMissileSpawn (AActor* th)
|
|||
th->y += th->vely >> shift;
|
||||
th->z += th->velz >> shift;
|
||||
|
||||
// killough 3/15/98: no dropoff (really = don't care for missiles)
|
||||
// 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));
|
||||
|
||||
if (!P_TryMove (th, th->x, th->y, false, false, tm))
|
||||
// killough 3/15/98: no dropoff (really = don't care for missiles)
|
||||
if (!(P_TryMove (th, th->x, th->y, false, false, tm)))
|
||||
{
|
||||
// [RH] Don't explode ripping missiles that spawn inside something
|
||||
if (th->BlockingMobj == NULL || !(th->flags2 & MF2_RIP) || (th->BlockingMobj->flags5 & MF5_DONTRIP))
|
||||
|
|
@ -4788,6 +4853,10 @@ bool P_CheckMissileSpawn (AActor* th)
|
|||
{
|
||||
th->Destroy ();
|
||||
}
|
||||
else if (MBFGrenade && th->BlockingLine != NULL )
|
||||
{
|
||||
P_BounceWall(th);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_ExplodeMissile (th, NULL, th->BlockingMobj);
|
||||
|
|
@ -5461,7 +5530,7 @@ void PrintMiscActorInfo(AActor * query)
|
|||
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);
|
||||
*/
|
||||
Printf("\nIts thing special and arguments are %s(%i, %i, %i, %i, %i), and its specials are %i and %i.",
|
||||
GetSpecialName(query->special), query->args[0], query->args[1],
|
||||
LineSpecialsInfo[query->special]->name, query->args[0], query->args[1],
|
||||
query->args[2], query->args[3], query->args[4],
|
||||
query->special1, query->special2);
|
||||
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue