mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- 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
|
@ -1,5 +1,8 @@
|
|||
September 14, 2009 (Changes by Graf Zahl)
|
||||
- Fixed: Argument count for UsePuzzleItem was wrong.
|
||||
- Added a few things from Gez's experimental build:
|
||||
* MBF grenade and bouncing code.
|
||||
* several compatibility options.
|
||||
* info CCMD to print extended actor information (not fully implemented yet)
|
||||
* summonmbf CCMD.
|
||||
* Beta BFG code pointer (but not the related missiles yet.)
|
||||
|
|
|
@ -118,7 +118,7 @@ Thing_SetSprite, 126, -1, -1)
|
|||
#endif
|
||||
DEFINE_SPECIAL(Thing_SetSpecial, 127, 5, 5, 5)
|
||||
DEFINE_SPECIAL(ThrustThingZ, 128, 4, 4, 4)
|
||||
DEFINE_SPECIAL(UsePuzzleItem, 129, 1, 1, 1)
|
||||
DEFINE_SPECIAL(UsePuzzleItem, 129, 2, 5, 5)
|
||||
DEFINE_SPECIAL(Thing_Activate, 130, 1, 1, 1)
|
||||
DEFINE_SPECIAL(Thing_Deactivate, 131, 1, 1, 1)
|
||||
DEFINE_SPECIAL(Thing_Remove, 132, 1, 1, 1)
|
||||
|
|
|
@ -309,7 +309,13 @@ enum
|
|||
MF6_DONTHARMSPECIES = 0x00000040, // Don't hurt one's own species with explosions (hitscans, too?)
|
||||
MF6_STEPMISSILE = 0x00000080, // Missile can "walk" up steps
|
||||
MF6_NOTELEFRAG = 0x00000100, // [HW] Actor can't be telefragged
|
||||
|
||||
MF6_TOUCHY = 0x00000200, // From MBF: killough 11/98: dies when solids touch it
|
||||
MF6_CANJUMP = 0x00000400, // From MBF: a dedicated flag instead of the BOUNCES+FLOAT+sentient combo
|
||||
MF6_JUMPDOWN = 0x00000800, // From MBF: generalization of dog behavior wrt. dropoffs.
|
||||
MF6_VULNERABLE = 0x00001000, // Actor can be damaged (even if not shootable).
|
||||
MF6_ARMED = 0x00002000, // From MBF: Object is armed (for MF6_TOUCHY objects)
|
||||
MF6_FALLING = 0x00004000, // From MBF: Object is falling (for pseudotorque simulation)
|
||||
MF6_LINEDONE = 0x00008000, // From MBF: Object has already run a line effect
|
||||
|
||||
// --- mobj.renderflags ---
|
||||
|
||||
|
|
|
@ -78,6 +78,7 @@ static FCompatOption Options[] =
|
|||
{ "setslopeoverflow", 0, BCOMPATF_SETSLOPEOVERFLOW },
|
||||
{ "resetplayerspeed", 0, BCOMPATF_RESETPLAYERSPEED },
|
||||
{ "spechitoverflow", 0, BCOMPATF_SPECHITOVERFLOW },
|
||||
{ "vileghosts", 0, BCOMPATF_VILEGHOSTS },
|
||||
|
||||
// list copied from g_mapinfo.cpp
|
||||
{ "shorttex", COMPATF_SHORTTEX, 0 },
|
||||
|
@ -101,6 +102,11 @@ static FCompatOption Options[] =
|
|||
{ "wallrun", COMPATF_WALLRUN, 0 }, // [GZ] Added for CC MAP29
|
||||
{ "anybossdeath", COMPATF_ANYBOSSDEATH, 0}, // [GZ] Added for UAC_DEAD
|
||||
{ "mushroom", COMPATF_MUSHROOM, 0},
|
||||
{ "mbfdehacked", COMPATF_MBFDEHACKED, 0},
|
||||
{ "mbftorque", COMPATF_MBFTORQUE, 0},
|
||||
{ "mbfmonstermove", COMPATF_MBFMONSTERMOVE, 0 },
|
||||
{ "corpsegibs", COMPATF_CORPSEGIBS, 0 },
|
||||
{ "noblockfriends", COMPATF_NOBLOCKFRIENDS, 0 },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -499,16 +499,22 @@ CUSTOM_CVAR(Int, compatmode, 0, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
|||
case 2: // same as 1 but stricter (NO_PASSMOBJ and INVISIBILITY are also set)
|
||||
v = COMPATF_SHORTTEX|COMPATF_STAIRINDEX|COMPATF_USEBLOCKING|COMPATF_NODOORLIGHT|
|
||||
COMPATF_TRACE|COMPATF_MISSILECLIP|COMPATF_SOUNDTARGET|COMPATF_NO_PASSMOBJ|COMPATF_LIMITPAIN|
|
||||
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF;
|
||||
COMPATF_DEHHEALTH|COMPATF_INVISIBILITY|COMPATF_CROSSDROPOFF|COMPATF_CORPSEGIBS;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MUSHROOM;
|
||||
case 3: // Boom compat mode
|
||||
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
case 4: // Old ZDoom compat mode
|
||||
v = COMPATF_SOUNDTARGET;
|
||||
break;
|
||||
|
||||
case 5: // MBF compat mode
|
||||
v = COMPATF_TRACE|COMPATF_SOUNDTARGET|COMPATF_BOOMSCROLL|COMPATF_MUSHROOM|
|
||||
COMPATF_MBFDEHACKED|COMPATF_MBFTORQUE|COMPATF_MBFMONSTERMOVE|COMPATF_NOBLOCKFRIENDS;
|
||||
break;
|
||||
|
||||
}
|
||||
compatflags = v;
|
||||
}
|
||||
|
@ -537,6 +543,11 @@ CVAR (Flag, compat_crossdropoff,compatflags, COMPATF_CROSSDROPOFF);
|
|||
CVAR (Flag, compat_anybossdeath,compatflags, COMPATF_ANYBOSSDEATH);
|
||||
CVAR (Flag, compat_minotaur, compatflags, COMPATF_MINOTAUR);
|
||||
CVAR (Flag, compat_mushroom, compatflags, COMPATF_MUSHROOM);
|
||||
CVAR (Flag, compat_mbfdehacked, compatflags, COMPATF_MBFDEHACKED);
|
||||
CVAR (Flag, compat_mbftorque, compatflags, COMPATF_MBFTORQUE);
|
||||
CVAR (Flag, compat_mbfmonstermove,compatflags, COMPATF_MBFMONSTERMOVE);
|
||||
CVAR (Flag, compat_corpsegibs, compatflags, COMPATF_CORPSEGIBS);
|
||||
CVAR (Flag, compat_noblockfriends,compatflags,COMPATF_NOBLOCKFRIENDS);
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -320,7 +320,12 @@ enum
|
|||
COMPATF_CROSSDROPOFF = 1 << 20, // monsters can't be pushed over dropoffs
|
||||
COMPATF_ANYBOSSDEATH = 1 << 21, // [GZ] Any monster which calls BOSSDEATH counts for level specials
|
||||
COMPATF_MINOTAUR = 1 << 22, // Minotaur's floor flame is exploded immediately when feet are clipped
|
||||
COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked oods.
|
||||
COMPATF_MUSHROOM = 1 << 23, // Force original velocity calculations for A_Mushroom in Dehacked mods.
|
||||
COMPATF_MBFDEHACKED = 1 << 24, // Allow a state's miscs to be out of offset ranges, for use as params.
|
||||
COMPATF_MBFTORQUE = 1 << 25, // Uses MBF-style pseudo torque simulation.
|
||||
COMPATF_MBFMONSTERMOVE = 1 << 26, // Monsters are affected by friction and pushers/pullers.
|
||||
COMPATF_CORPSEGIBS = 1 << 27, // Crushed monsters are turned into gibs, rather than replaced by gibs.
|
||||
COMPATF_NOBLOCKFRIENDS = 1 << 28, // Friendly monsters aren't blocked by monster-blocking lines.
|
||||
};
|
||||
|
||||
// Emulate old bugs for select maps. These are not exposed by a cvar
|
||||
|
@ -330,6 +335,7 @@ enum
|
|||
BCOMPATF_SETSLOPEOVERFLOW = 1 << 0, // SetSlope things can overflow
|
||||
BCOMPATF_RESETPLAYERSPEED = 1 << 1, // Set player speed to 1.0 when changing maps
|
||||
BCOMPATF_SPECHITOVERFLOW = 1 << 2, // Emulate spechit overflow (e.g. Strain MAP07)
|
||||
BCOMPATF_VILEGHOSTS = 1 << 3, // Monsters' radius and height aren't restored properly when resurrected.
|
||||
};
|
||||
|
||||
// phares 3/20/98:
|
||||
|
|
|
@ -1356,6 +1356,11 @@ MapFlagHandlers[] =
|
|||
{ "compat_anybossdeath", MITYPE_COMPATFLAG, COMPATF_ANYBOSSDEATH},
|
||||
{ "compat_minotaur", MITYPE_COMPATFLAG, COMPATF_MINOTAUR},
|
||||
{ "compat_mushroom", MITYPE_COMPATFLAG, COMPATF_MUSHROOM},
|
||||
{ "compat_mbfdehacked", MITYPE_COMPATFLAG, COMPATF_MBFDEHACKED},
|
||||
{ "compat_mbftorque", MITYPE_COMPATFLAG, COMPATF_MBFTORQUE},
|
||||
{ "compat_mbfmonstermove", MITYPE_COMPATFLAG, COMPATF_MBFMONSTERMOVE},
|
||||
{ "compat_corpsegibs", MITYPE_COMPATFLAG, COMPATF_CORPSEGIBS},
|
||||
{ "compat_noblockfriends", MITYPE_COMPATFLAG, COMPATF_NOBLOCKFRIENDS},
|
||||
{ "cd_start_track", MITYPE_EATNEXT, 0, 0 },
|
||||
{ "cd_end1_track", MITYPE_EATNEXT, 0, 0 },
|
||||
{ "cd_end2_track", MITYPE_EATNEXT, 0, 0 },
|
||||
|
|
|
@ -148,12 +148,13 @@ value_t OffOn[2] = {
|
|||
{ 1.0, "Off" }
|
||||
};
|
||||
|
||||
value_t CompatModes[5] = {
|
||||
value_t CompatModes[6] = {
|
||||
{ 0.0, "Default" },
|
||||
{ 1.0, "Doom" },
|
||||
{ 2.0, "Doom (strict)" },
|
||||
{ 3.0, "Boom" },
|
||||
{ 4.0, "ZDoom 2.0.63" }
|
||||
{ 4.0, "ZDoom 2.0.63" },
|
||||
{ 5.0, "MBF" },
|
||||
};
|
||||
|
||||
menu_t *CurrentMenu;
|
||||
|
@ -1079,7 +1080,7 @@ static menu_t DMFlagsMenu =
|
|||
*=======================================*/
|
||||
|
||||
static menuitem_t CompatibilityItems[] = {
|
||||
{ discrete, "Compatibility mode", {&compatmode}, {5.0}, {1.0}, {0.0}, {CompatModes} },
|
||||
{ discrete, "Compatibility mode", {&compatmode}, {6.0}, {1.0}, {0.0}, {CompatModes} },
|
||||
{ redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} },
|
||||
{ bitflag, "Find shortest textures like Doom", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_SHORTTEX} },
|
||||
{ bitflag, "Use buggier stair building", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_STAIRINDEX} },
|
||||
|
@ -1105,6 +1106,11 @@ static menuitem_t CompatibilityItems[] = {
|
|||
{ bitflag, "Allow any bossdeath for level special", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_ANYBOSSDEATH} },
|
||||
{ bitflag, "No Minotaur floor flames in water", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MINOTAUR} },
|
||||
{ bitflag, "Original A_Mushroom speed in DEH mods", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MUSHROOM} },
|
||||
{ bitflag, "Allow MBF DeHackEd parameters", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MBFDEHACKED} },
|
||||
{ bitflag, "Allow MBF pseudo-torque effects", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MBFTORQUE} },
|
||||
{ bitflag, "Monster movement is affected by effects", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_MBFMONSTERMOVE} },
|
||||
{ bitflag, "Crushed monsters can be resurrected", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_CORPSEGIBS} },
|
||||
{ bitflag, "Friendly monsters aren't blocked", {&compatflags}, {0}, {0}, {0}, {(value_t *)COMPATF_NOBLOCKFRIENDS} },
|
||||
|
||||
{ discrete, "Interpolate monster movement", {&nomonsterinterpolation}, {2.0}, {0.0}, {0.0}, {NoYes} },
|
||||
};
|
||||
|
|
|
@ -178,6 +178,7 @@ xx(No)
|
|||
xx(Greetings)
|
||||
xx(Idle)
|
||||
xx(GenericFreezeDeath)
|
||||
xx(GenericCrush)
|
||||
|
||||
// Compatible death names for the decorate parser.
|
||||
xx(XDeath)
|
||||
|
|
|
@ -371,6 +371,7 @@ bool P_HitFriend(AActor * self)
|
|||
// Move in the current direction,
|
||||
// returns false if the move is blocked.
|
||||
//
|
||||
|
||||
bool P_Move (AActor *actor)
|
||||
{
|
||||
|
||||
|
@ -392,8 +393,9 @@ bool P_Move (AActor *actor)
|
|||
|
||||
// [RH] Instead of yanking non-floating monsters to the ground,
|
||||
// let gravity drop them down, unless they're moving down a step.
|
||||
if (!(actor->flags & MF_NOGRAVITY) && actor->z > actor->floorz
|
||||
&& !(actor->flags2 & MF2_ONMOBJ))
|
||||
// [GZ] Let jumping actors jump.
|
||||
if (!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
|
||||
&& actor->z > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
|
||||
{
|
||||
if (actor->z > actor->floorz + actor->MaxStepHeight)
|
||||
{
|
||||
|
@ -410,20 +412,23 @@ bool P_Move (AActor *actor)
|
|||
|
||||
speed = actor->Speed;
|
||||
|
||||
#if 0 // [RH] I'm not so sure this is such a good idea
|
||||
// killough 10/98: make monsters get affected by ice and sludge too:
|
||||
movefactor = P_GetMoveFactor (actor, &friction);
|
||||
// [RH] I'm not so sure this is such a good idea
|
||||
// [GZ] That's why it's compat-optioned.
|
||||
if (compatflags & COMPATF_MBFMONSTERMOVE)
|
||||
{
|
||||
// killough 10/98: make monsters get affected by ice and sludge too:
|
||||
movefactor = P_GetMoveFactor (actor, &friction);
|
||||
|
||||
if (friction < ORIG_FRICTION)
|
||||
{ // sludge
|
||||
speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
|
||||
* speed) / ORIG_FRICTION_FACTOR;
|
||||
if (speed == 0)
|
||||
{ // always give the monster a little bit of speed
|
||||
speed = ksgn(actor->Speed);
|
||||
if (friction < ORIG_FRICTION)
|
||||
{ // sludge
|
||||
speed = ((ORIG_FRICTION_FACTOR - (ORIG_FRICTION_FACTOR-movefactor)/2)
|
||||
* speed) / ORIG_FRICTION_FACTOR;
|
||||
if (speed == 0)
|
||||
{ // always give the monster a little bit of speed
|
||||
speed = ksgn(actor->Speed);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
tryx = (origx = actor->x) + (deltax = FixedMul (speed, xspeed[actor->movedir]));
|
||||
tryy = (origy = actor->y) + (deltay = FixedMul (speed, yspeed[actor->movedir]));
|
||||
|
@ -485,7 +490,7 @@ bool P_Move (AActor *actor)
|
|||
|
||||
if (!try_ok)
|
||||
{
|
||||
if ((actor->flags & MF_FLOAT) && tm.floatok)
|
||||
if (((actor->flags6 & MF6_CANJUMP)||(actor->flags & MF_FLOAT)) && tm.floatok)
|
||||
{ // must adjust height
|
||||
fixed_t savedz = actor->z;
|
||||
|
||||
|
@ -2220,13 +2225,31 @@ static bool P_CheckForResurrection(AActor *self, bool usevilestates)
|
|||
S_Sound (corpsehit, CHAN_BODY, "vile/raise", 1, ATTN_IDLE);
|
||||
info = corpsehit->GetDefault ();
|
||||
|
||||
corpsehit->height = info->height; // [RH] Use real mobj height
|
||||
corpsehit->radius = info->radius; // [RH] Use real radius
|
||||
/*
|
||||
// Make raised corpses look ghostly
|
||||
if (corpsehit->alpha > TRANSLUC50)
|
||||
corpsehit->alpha /= 2;
|
||||
*/
|
||||
if (ib_compatflags & BCOMPATF_VILEGHOSTS)
|
||||
{
|
||||
corpsehit->height <<= 2;
|
||||
// [GZ] This was a commented-out feature, so let's make use of it,
|
||||
// but only for ghost monsters so that they are visibly different.
|
||||
if (corpsehit->height == 0)
|
||||
{
|
||||
// Make raised corpses look ghostly
|
||||
if (corpsehit->alpha > TRANSLUC50)
|
||||
{
|
||||
corpsehit->alpha /= 2;
|
||||
}
|
||||
// This will only work if the render style is changed as well.
|
||||
if (corpsehit->RenderStyle == LegacyRenderStyles[STYLE_Normal])
|
||||
{
|
||||
corpsehit->RenderStyle = STYLE_Translucent;
|
||||
}
|
||||
}
|
||||
corpsehit->Translation = info->Translation; // Clean up bloodcolor translation from crushed corpses
|
||||
}
|
||||
else
|
||||
{
|
||||
corpsehit->height = info->height; // [RH] Use real mobj height
|
||||
corpsehit->radius = info->radius; // [RH] Use real radius
|
||||
}
|
||||
corpsehit->flags = info->flags;
|
||||
corpsehit->flags2 = info->flags2;
|
||||
corpsehit->flags3 = info->flags3;
|
||||
|
|
|
@ -883,7 +883,7 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
|
|||
FState * woundstate = NULL;
|
||||
PainChanceList * pc = NULL;
|
||||
|
||||
if (target == NULL || !(target->flags & MF_SHOOTABLE))
|
||||
if (target == NULL || !((target->flags & MF_SHOOTABLE) || (target->flags6 & MF6_VULNERABLE)))
|
||||
{ // Shouldn't happen
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -3250,13 +3250,3 @@ int P_FindLineSpecial (const char *string, int *min_args, int *max_args)
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *GetSpecialName(int num)
|
||||
{
|
||||
for(int i = 0; i < countof(LineSpecialNames); i++)
|
||||
{
|
||||
if (LineSpecialNames[i].number == num)
|
||||
return LineSpecialNames[i].name;
|
||||
}
|
||||
return "(unknown)";
|
||||
}
|
|
@ -196,6 +196,5 @@ typedef int (*lnSpecFunc)(struct line_t *line,
|
|||
extern lnSpecFunc LineSpecials[256];
|
||||
|
||||
int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL);
|
||||
const char *GetSpecialName(int num);
|
||||
|
||||
#endif //__P_LNSPEC_H__
|
||||
|
|
|
@ -380,10 +380,12 @@ void P_FakeZMovement (AActor *mo);
|
|||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor, FCheckPosition &tm);
|
||||
bool P_TryMove (AActor* thing, fixed_t x, fixed_t y, bool dropoff, const secplane_t * onfloor = NULL);
|
||||
bool P_CheckMove(AActor *thing, fixed_t x, fixed_t y);
|
||||
void P_ApplyTorque(AActor *mo);
|
||||
bool P_TeleportMove (AActor* thing, fixed_t x, fixed_t y, fixed_t z, bool telefrag); // [RH] Added z and telefrag parameters
|
||||
void P_PlayerStartStomp (AActor *actor); // [RH] Stomp on things for a newly spawned player
|
||||
void P_SlideMove (AActor* mo, fixed_t tryx, fixed_t tryy, int numsteps);
|
||||
bool P_BounceWall (AActor *mo);
|
||||
bool P_BounceActor (AActor *mo, AActor * BlockingMobj);
|
||||
bool P_CheckSight (const AActor* t1, const AActor* t2, int flags=0);
|
||||
void P_ResetSightCounters (bool full);
|
||||
void P_UseLines (player_t* player);
|
||||
|
|
106
src/p_map.cpp
106
src/p_map.cpp
|
@ -590,17 +590,25 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!(tm.thing->flags & MF_MISSILE) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE)))
|
||||
{
|
||||
// MBF bouncers are treated as missiles here.
|
||||
bool Projectile = (tm.thing->flags & MF_MISSILE || tm.thing->BounceFlags & BOUNCE_MBF);
|
||||
// MBF considers that friendly monsters are not blocked by monster-blocking lines.
|
||||
// This is added here as a compatibility option. Note that monsters that are dehacked
|
||||
// into being friendly with the MBF flag automatically gain MF3_NOBLOCKMONST, so this
|
||||
// just optionally generalizes the behavior to other friendly monsters.
|
||||
bool NotBlocked = ((tm.thing->flags3 & MF3_NOBLOCKMONST)
|
||||
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (tm.thing->flags & MF_FRIENDLY)));
|
||||
|
||||
if (!(Projectile) || (ld->flags & (ML_BLOCKEVERYTHING|ML_BLOCKPROJECTILE))) {
|
||||
if (ld->flags & ML_RAILING)
|
||||
{
|
||||
rail = true;
|
||||
}
|
||||
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
|
||||
(!(tm.thing->flags3 & MF3_NOBLOCKMONST) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
|
||||
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
|
||||
((tm.thing->flags & MF_MISSILE) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
|
||||
((ld->flags & ML_BLOCK_FLOATERS) && (tm.thing->flags & MF_FLOAT))) // block floaters
|
||||
else if ((ld->flags & (ML_BLOCKING|ML_BLOCKEVERYTHING)) || // explicitly blocking everything
|
||||
(!(NotBlocked) && (ld->flags & ML_BLOCKMONSTERS)) || // block monsters only
|
||||
(tm.thing->player != NULL && (ld->flags & ML_BLOCK_PLAYERS)) || // block players
|
||||
((Projectile) && (ld->flags & ML_BLOCKPROJECTILE)) || // block projectiles
|
||||
((tm.thing->flags & MF_FLOAT) && (ld->flags & ML_BLOCK_FLOATERS))) // block floaters
|
||||
{
|
||||
if (tm.thing->flags2 & MF2_BLASTED)
|
||||
{
|
||||
|
@ -754,6 +762,13 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
bool solid;
|
||||
int damage;
|
||||
|
||||
if (!((thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) || thing->flags6 & MF6_TOUCHY))
|
||||
return true; // can't hit thing
|
||||
|
||||
fixed_t blockdist = thing->radius + tm.thing->radius;
|
||||
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
|
||||
return true;
|
||||
|
||||
// don't clip against self
|
||||
if (thing == tm.thing)
|
||||
return true;
|
||||
|
@ -764,13 +779,6 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
if ((tm.thing->flags6 & MF6_THRUSPECIES) && (tm.thing->GetSpecies() == thing->GetSpecies()))
|
||||
return true;
|
||||
|
||||
if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE)) )
|
||||
return true; // can't hit thing
|
||||
|
||||
fixed_t blockdist = thing->radius + tm.thing->radius;
|
||||
if ( abs(thing->x - tm.x) >= blockdist || abs(thing->y - tm.y) >= blockdist)
|
||||
return true;
|
||||
|
||||
tm.thing->BlockingMobj = thing;
|
||||
topz = thing->z + thing->height;
|
||||
if (!(i_compatflags & COMPATF_NO_PASSMOBJ) && !(tm.thing->flags & (MF_FLOAT|MF_MISSILE|MF_SKULLFLY|MF_NOGRAVITY)) &&
|
||||
|
@ -806,6 +814,26 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// touchy object is alive, toucher is solid
|
||||
if (thing->flags6 & MF6_TOUCHY && tm.thing->flags & MF_SOLID && thing->health > 0 &&
|
||||
// Thing is an armed mine or a sentient thing
|
||||
(thing->flags6 & MF6_ARMED || thing->IsSentient()) &&
|
||||
// either different classes or players
|
||||
(thing->player || thing->GetClass() != tm.thing->GetClass()) &&
|
||||
// or different species if DONTHARMSPECIES
|
||||
(!(thing->flags6 & MF6_DONTHARMSPECIES) || thing->GetSpecies() != tm.thing->GetSpecies()) &&
|
||||
// touches vertically
|
||||
thing->z + thing->height >= tm.thing->z && tm.thing->z + tm.thing->height >= thing->z &&
|
||||
// prevents lost souls from exploding when fired by pain elementals
|
||||
(thing->master != tm.thing && tm.thing->master != thing))
|
||||
// Difference with MBF: MBF hardcodes the LS/PE check and lets actors of the same species
|
||||
// but different classes trigger the touchiness, but that seems less straightforwards.
|
||||
{
|
||||
thing->flags6 &= ~MF6_ARMED; // Disarm
|
||||
P_DamageMobj (thing, NULL, NULL, thing->health, NAME_None, DMG_FORCED); // kill object
|
||||
return true;
|
||||
}
|
||||
// Check for skulls slamming into things
|
||||
if (tm.thing->flags & MF_SKULLFLY)
|
||||
{
|
||||
|
@ -839,8 +867,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
LineSpecials[thing->special] (NULL, tm.thing, false, thing->args[0],
|
||||
thing->args[1], thing->args[2], thing->args[3], thing->args[4]);
|
||||
}
|
||||
// Check for missile
|
||||
if (tm.thing->flags & MF_MISSILE)
|
||||
// Check for missile or non-solid MBF bouncer
|
||||
if (tm.thing->flags & MF_MISSILE || ((tm.thing->BounceFlags & BOUNCE_MBF) && !(tm.thing->flags & MF_SOLID)))
|
||||
{
|
||||
// Check for a non-shootable mobj
|
||||
if (thing->flags2 & MF2_NONSHOOTABLE)
|
||||
|
@ -891,7 +919,8 @@ bool PIT_CheckThing (AActor *thing, FCheckPosition &tm)
|
|||
|
||||
// [RH] What is the point of this check, again? In Hexen, it is unconditional,
|
||||
// but here we only do it if the missile's damage is 0.
|
||||
if ((tm.thing->BounceFlags & BOUNCE_Actors) && tm.thing->Damage == 0)
|
||||
// MBF bouncer might have a non-0 damage value, but they must not deal damage on impact either.
|
||||
if ((tm.thing->BounceFlags & BOUNCE_Actors) && (tm.thing->Damage == 0 || !(tm.thing->flags & MF_MISSILE)))
|
||||
{
|
||||
return (tm.thing->target == thing || !(thing->flags & MF_SOLID));
|
||||
}
|
||||
|
@ -1707,6 +1736,12 @@ bool P_TryMove (AActor *thing, fixed_t x, fixed_t y,
|
|||
oldAboveFakeCeiling = eyez > oldsec->heightsec->ceilingplane.ZatPoint (thing->x, thing->y);
|
||||
}
|
||||
|
||||
// Borrowed from MBF:
|
||||
if (thing->BounceFlags & BOUNCE_MBF && // killough 8/13/98
|
||||
!(thing->flags & (MF_MISSILE|MF_NOGRAVITY)) &&
|
||||
!thing->IsSentient() && tm.floorz - thing->z > 16*FRACUNIT)
|
||||
return false; // too big a step up for MBF bouncers under gravity
|
||||
|
||||
// the move is ok, so link the thing into its new position
|
||||
thing->UnlinkFromWorld ();
|
||||
|
||||
|
@ -1973,8 +2008,6 @@ struct FSlide
|
|||
bool BounceWall (AActor *mo);
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// P_HitSlideLine
|
||||
// Adjusts the xmove / ymove
|
||||
|
@ -2153,7 +2186,8 @@ void FSlide::SlideTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_
|
|||
{
|
||||
goto isblocking;
|
||||
}
|
||||
if (li->flags & ML_BLOCKMONSTERS && !(slidemo->flags3 & MF3_NOBLOCKMONST))
|
||||
if (li->flags & ML_BLOCKMONSTERS && !((slidemo->flags3 & MF3_NOBLOCKMONST)
|
||||
|| ((i_compatflags & COMPATF_NOBLOCKFRIENDS) && (slidemo->flags & MF_FRIENDLY))))
|
||||
{
|
||||
goto isblocking;
|
||||
}
|
||||
|
@ -2596,7 +2630,10 @@ bool FSlide::BounceWall (AActor *mo)
|
|||
// The amount of bounces is limited
|
||||
if (mo->bouncecount>0 && --mo->bouncecount==0)
|
||||
{
|
||||
P_ExplodeMissile(mo, NULL, NULL);
|
||||
if (mo->flags & MF_MISSILE)
|
||||
P_ExplodeMissile(mo, NULL, NULL);
|
||||
else
|
||||
mo->Die(NULL, NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2637,7 +2674,28 @@ bool P_BounceWall (AActor *mo)
|
|||
return slide.BounceWall(mo);
|
||||
}
|
||||
|
||||
|
||||
extern FRandom pr_bounce ("Bounce");
|
||||
bool P_BounceActor (AActor *mo, AActor * BlockingMobj)
|
||||
{
|
||||
if (mo && BlockingMobj && ((mo->BounceFlags & BOUNCE_AllActors)
|
||||
|| ((mo->flags & MF_MISSILE) && (BlockingMobj->flags2 & MF2_REFLECTIVE)
|
||||
|| ((!BlockingMobj->player) && (!(BlockingMobj->flags3 & MF3_ISMONSTER))))
|
||||
))
|
||||
{
|
||||
fixed_t speed;
|
||||
angle_t 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, mo->wallbouncefactor); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
mo->angle = angle;
|
||||
angle >>= ANGLETOFINESHIFT;
|
||||
mo->velx = FixedMul (speed, finecosine[angle]);
|
||||
mo->vely = FixedMul (speed, finesine[angle]);
|
||||
mo->PlayBounceSound(true);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
|
@ -3976,7 +4034,9 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
|
|||
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if (!(thing->flags & MF_SHOOTABLE) )
|
||||
// Vulnerable actors can be damaged by radius attacks even if not shootable
|
||||
// Used to emulate MBF's vulnerability of non-missile bouncers to explosions.
|
||||
if (!((thing->flags & MF_SHOOTABLE) || (thing->flags6 & MF6_VULNERABLE)))
|
||||
continue;
|
||||
|
||||
// Boss spider and cyborg and Heretic's ep >= 2 bosses
|
||||
|
|
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.",
|
||||
|
|
|
@ -1737,7 +1737,17 @@ void DPusher::Tick ()
|
|||
|
||||
while ((thing = it.Next()))
|
||||
{
|
||||
if ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP))
|
||||
// Normal ZDoom is based only on the WINDTHRUST flag, with the noclip cheat as an exemption.
|
||||
bool pusharound = ((thing->flags2 & MF2_WINDTHRUST) && !(thing->flags & MF_NOCLIP));
|
||||
|
||||
// MBF allows any sentient or shootable thing to be affected, but players with a fly cheat aren't.
|
||||
if (compatflags & COMPATF_MBFMONSTERMOVE)
|
||||
{
|
||||
pusharound = ((pusharound || (thing->IsSentient()) || (thing->flags & MF_SHOOTABLE)) // Add categories here
|
||||
&& (!(thing->player && (thing->flags & (MF_NOGRAVITY))))); // Exclude flying players here
|
||||
}
|
||||
|
||||
if ((pusharound) )
|
||||
{
|
||||
int sx = m_X;
|
||||
int sy = m_Y;
|
||||
|
|
|
@ -1653,7 +1653,7 @@ void P_MovePlayer (player_t *player)
|
|||
mo->angle += cmd->ucmd.yaw << 16;
|
||||
}
|
||||
|
||||
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ);
|
||||
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ) || (mo->BounceFlags & BOUNCE_MBF);
|
||||
|
||||
// killough 10/98:
|
||||
//
|
||||
|
@ -2535,7 +2535,7 @@ void player_t::Serialize (FArchive &arc)
|
|||
<< ConversationPC
|
||||
<< ConversationNPCAngle
|
||||
<< ConversationFaceTalker;
|
||||
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
arc << frags[i];
|
||||
for (i = 0; i < NUMPSPRITES; i++)
|
||||
|
|
|
@ -48,6 +48,8 @@ enum EStateDefineFlags
|
|||
SDF_WAIT = 3,
|
||||
SDF_LABEL = 4,
|
||||
SDF_INDEX = 5,
|
||||
SDF_MASK = 7,
|
||||
SDF_DEHACKED = 8, // Identify a state as having been modified by a dehacked lump
|
||||
};
|
||||
|
||||
struct FStateDefine
|
||||
|
|
|
@ -214,6 +214,10 @@ static FFlagDef ActorFlags[]=
|
|||
DEFINE_FLAG(MF6, DONTHARMSPECIES, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, STEPMISSILE, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, NOTELEFRAG, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, TOUCHY, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, CANJUMP, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, JUMPDOWN, AActor, flags6),
|
||||
DEFINE_FLAG(MF6, VULNERABLE, AActor, flags6),
|
||||
|
||||
// Effect flags
|
||||
DEFINE_FLAG(FX, VISIBILITYPULSE, AActor, effects),
|
||||
|
|
|
@ -62,6 +62,8 @@ DEFINE_MEMBER_VARIABLE(floorz, AActor)
|
|||
DEFINE_MEMBER_VARIABLE(health, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(pitch, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(special, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(special1, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(special2, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(tid, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(TIDtoHate, AActor)
|
||||
DEFINE_MEMBER_VARIABLE(waterlevel, AActor)
|
||||
|
|
|
@ -269,6 +269,9 @@ ACTOR Actor native //: Thinker
|
|||
"----" A 5 A_GenericFreezeDeath
|
||||
"----" A 1 A_FreezeDeathChunks
|
||||
Wait
|
||||
GenericCrush:
|
||||
POL5 A -1
|
||||
Stop
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,8 +87,7 @@ ACTOR RealGibs
|
|||
States
|
||||
{
|
||||
Spawn:
|
||||
POL5 A -1
|
||||
Stop
|
||||
goto GenericCrush
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -360,7 +360,7 @@ StateMap
|
|||
BloodyTwitch, Spawn, 4, // S_BLOODYTWITCH - S_BLOODYTWITCH4
|
||||
DoomUnusedStates, Label2, 2, // S_DEADTORSO - S_DEADBOTTOM
|
||||
HeadsOnAStick, Spawn, 1, // S_HEADSONSTICK
|
||||
RealGibs, Spawn, 1, // S_GIBS
|
||||
Actor, GenericCrush, 1, // S_GIBS
|
||||
HeadOnAStick, Spawn, 1, // S_HEADONASTICK
|
||||
HeadCandles, Spawn, 2, // S_HEADCANDLES - S_HEADCANDLES2
|
||||
DeadStick, Spawn, 1, // S_DEADSTICK
|
||||
|
|
Loading…
Reference in a new issue