mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-19 07:30:59 +00:00
- MBF21: more work on flags.
* added handlers for the missing upper flags in the first flag word. * refactored some code related to MF_BOUNCES to adapt to other flags' changes to avoid constant property updates for too many flags. * treat anything with RF_ZDOOMTRANS as non-translucent for the purpose of the flag checks.
This commit is contained in:
parent
e82fd43313
commit
9082ef7d49
6 changed files with 157 additions and 35 deletions
|
@ -1154,8 +1154,7 @@ static int PatchThing (int thingy)
|
|||
while ((result = GetLine ()) == 1)
|
||||
{
|
||||
char *endptr;
|
||||
uint64_t val64 = strtoull (Line2, &endptr, 10);
|
||||
uint32_t val = (uint32_t)val64;
|
||||
uint32_t val = (uint32_t)strtoull (Line2, &endptr, 10);
|
||||
size_t linelen = strlen (Line1);
|
||||
|
||||
if (linelen == 10 && stricmp (Line1, "Hit points") == 0)
|
||||
|
@ -1174,6 +1173,7 @@ static int PatchThing (int thingy)
|
|||
{
|
||||
info->Alpha = DEHToDouble(val);
|
||||
info->RenderStyle = STYLE_Translucent;
|
||||
info->renderflags &= ~RF_ZDOOMTRANS;
|
||||
hadTranslucency = true;
|
||||
hadStyle = true;
|
||||
}
|
||||
|
@ -1474,10 +1474,10 @@ static int PatchThing (int thingy)
|
|||
// This is different from BOUNCE_Heretic behavior as in Heretic the missiles
|
||||
// die when they bounce, while in MBF they will continue to bounce until they
|
||||
// collide with a wall or a solid actor.
|
||||
if (value[0] & MF_MISSILE) info->BounceFlags = BOUNCE_Classic;
|
||||
if (value[0] & MF_MISSILE) info->BounceFlags = BOUNCE_Classic | BOUNCE_DEH;
|
||||
// MBF bouncing actors that do not have the missile flag will also rebound on
|
||||
// walls, and this does correspond roughly to the ZDoom bounce style.
|
||||
else info->BounceFlags = BOUNCE_Grenade;
|
||||
else info->BounceFlags = BOUNCE_Grenade | BOUNCE_DEH;
|
||||
|
||||
// MBF grenades are dehacked rockets that gain the BOUNCES flag but
|
||||
// lose the MISSILE flag, so they can be identified here easily.
|
||||
|
@ -1487,27 +1487,13 @@ static int PatchThing (int thingy)
|
|||
info->effects |= FX_GRENADE; // by grenade trail
|
||||
}
|
||||
|
||||
// MBF bounce factors depend on flag combos:
|
||||
const double MBF_BOUNCE_NOGRAVITY = 1; // With NOGRAVITY: full momentum
|
||||
const double MBF_BOUNCE_FLOATDROPOFF = 0.85; // With FLOAT and DROPOFF: 85%
|
||||
const double MBF_BOUNCE_FLOAT = 0.7; // With FLOAT alone: 70%
|
||||
const double MBF_BOUNCE_DEFAULT = 0.45; // Without the above flags: 45%
|
||||
const double MBF_BOUNCE_WALL = 0.5; // Bouncing off walls: 50%
|
||||
// bounce factors are dynamic, we only set some defaults here.
|
||||
info->bouncefactor = 0.45;
|
||||
info->wallbouncefactor = 0.85;
|
||||
|
||||
info->bouncefactor = ((value[0] & MF_NOGRAVITY) ? MBF_BOUNCE_NOGRAVITY
|
||||
: (value[0] & MF_FLOAT) ? (value[0] & MF_DROPOFF) ? MBF_BOUNCE_FLOATDROPOFF
|
||||
: MBF_BOUNCE_FLOAT : MBF_BOUNCE_DEFAULT);
|
||||
|
||||
info->wallbouncefactor = ((value[0] & MF_NOGRAVITY) ? MBF_BOUNCE_NOGRAVITY : MBF_BOUNCE_WALL);
|
||||
|
||||
// MBF sentient actors with BOUNCE and FLOAT are able to "jump" by floating up.
|
||||
if (info->IsSentient())
|
||||
{
|
||||
if (value[0] & MF_FLOAT) info->flags6 |= MF6_CANJUMP;
|
||||
}
|
||||
// Non sentient actors can be damaged but they shouldn't bleed.
|
||||
else
|
||||
if (!info->IsSentient())
|
||||
{
|
||||
// Non sentient actors can be damaged but they shouldn't bleed.
|
||||
value[0] |= MF_NOBLOOD;
|
||||
}
|
||||
}
|
||||
|
@ -1581,6 +1567,7 @@ static int PatchThing (int thingy)
|
|||
else if (value[2] & 4)
|
||||
info->Alpha = 0.75;
|
||||
info->RenderStyle = STYLE_Translucent;
|
||||
info->renderflags &= ~RF_ZDOOMTRANS;
|
||||
}
|
||||
if (value[2] & 8)
|
||||
info->renderflags |= RF_INVISIBLE;
|
||||
|
@ -3652,6 +3639,7 @@ struct FlagHandler
|
|||
#define F2(flag) { [](AActor* a) { a->flags2 |= flag; }, [](AActor* a) { a->flags2 &= ~flag; }, [](AActor* a)->bool { return a->flags2 & flag; } }
|
||||
#define F3(flag) { [](AActor* a) { a->flags3 |= flag; }, [](AActor* a) { a->flags3 &= ~flag; }, [](AActor* a)->bool { return a->flags3 & flag; } }
|
||||
#define F4(flag) { [](AActor* a) { a->flags4 |= flag; }, [](AActor* a) { a->flags4 &= ~flag; }, [](AActor* a)->bool { return a->flags4 & flag; } }
|
||||
#define F6(flag) { [](AActor* a) { a->flags6 |= flag; }, [](AActor* a) { a->flags6 &= ~flag; }, [](AActor* a)->bool { return a->flags6 & flag; } }
|
||||
#define F8(flag) { [](AActor* a) { a->flags8 |= flag; }, [](AActor* a) { a->flags8 &= ~flag; }, [](AActor* a)->bool { return a->flags8 & flag; } }
|
||||
#define DEPF(flag) { [](AActor* a) { HandleDeprecatedFlags(a, nullptr, true, flag); }, [](AActor* a) { HandleDeprecatedFlags(a, nullptr, false, flag); }, [](AActor* a)->bool { return CheckDeprecatedFlags(a, nullptr, flag); } }
|
||||
|
||||
|
@ -3741,6 +3729,99 @@ void ClearFullVol(AActor* a)
|
|||
a->flags3 &= ~MF3_FULLVOLDEATH;
|
||||
}
|
||||
|
||||
void SetTranslucent(AActor* a)
|
||||
{
|
||||
a->RenderStyle = STYLE_Translucent;
|
||||
a->Alpha = 0.5;
|
||||
a->renderflags &= ~RF_ZDOOMTRANS;
|
||||
}
|
||||
|
||||
void ClearTranslucent(AActor* a)
|
||||
{
|
||||
a->RenderStyle = STYLE_Normal;
|
||||
a->Alpha = 1;
|
||||
a->renderflags &= ~RF_ZDOOMTRANS;
|
||||
}
|
||||
|
||||
bool CheckTranslucent(AActor* a)
|
||||
{
|
||||
// This is solely for MBF21. It will treat all objects with ZDOOMTRANS as non-translucent to ensure consistent results.
|
||||
// This also means that all translucency changes via Dehacked need to clear this flag.
|
||||
return !(a->renderflags & RF_ZDOOMTRANS) && a->Alpha < 1 - FLT_EPSILON;
|
||||
}
|
||||
|
||||
constexpr int t0 = 0;
|
||||
constexpr int t1 = TRANSLATION(TRANSLATION_Standard, 0);
|
||||
constexpr int t2 = TRANSLATION(TRANSLATION_Standard, 1);
|
||||
constexpr int t3 = TRANSLATION(TRANSLATION_Standard, 2);
|
||||
|
||||
void SetTranslation1(AActor* a)
|
||||
{
|
||||
if (a->Translation == t2 || a->Translation == t3) a->Translation = t3;
|
||||
else a->Translation = t1;
|
||||
}
|
||||
|
||||
void ClearTranslation1(AActor* a)
|
||||
{
|
||||
if (a->Translation == t3 || a->Translation == t2) a->Translation = t2;
|
||||
else a->Translation = t0;
|
||||
}
|
||||
|
||||
bool CheckTranslation1(AActor* a)
|
||||
{
|
||||
return a->Translation == t1 || a->Translation == t3;
|
||||
}
|
||||
|
||||
void SetTranslation2(AActor* a)
|
||||
{
|
||||
if (a->Translation == t1 || a->Translation == t3) a->Translation = t3;
|
||||
else a->Translation = t2;
|
||||
}
|
||||
|
||||
void ClearTranslation2(AActor* a)
|
||||
{
|
||||
if (a->Translation == t3 || a->Translation == t1) a->Translation = t1;
|
||||
else a->Translation = t0;
|
||||
}
|
||||
|
||||
bool CheckTranslation2(AActor* a)
|
||||
{
|
||||
return a->Translation == t2 || a->Translation == t3;
|
||||
}
|
||||
|
||||
// Bounces is very complex...
|
||||
void SetBounces(AActor* info)
|
||||
{
|
||||
info->flags6 |= MF6_VULNERABLE;
|
||||
info->flags3 |= MF3_NOBLOCKMONST;
|
||||
info->flags4 |= (MF4_FORCERADIUSDMG | MF4_DONTHARMCLASS);
|
||||
info->effects &= ~FX_ROCKET; // disable rocket trail if set.
|
||||
|
||||
if (info->flags & MF_MISSILE) info->BounceFlags = BOUNCE_Classic | BOUNCE_DEH;
|
||||
else info->BounceFlags = BOUNCE_Grenade | BOUNCE_DEH;
|
||||
|
||||
}
|
||||
|
||||
void ClearBounces(AActor* info)
|
||||
{
|
||||
info->flags6 &= ~MF6_VULNERABLE;
|
||||
info->flags3 &= ~MF3_NOBLOCKMONST;
|
||||
info->flags4 &= ~(MF4_FORCERADIUSDMG | MF4_DONTHARMCLASS);
|
||||
info->BounceFlags = 0;
|
||||
}
|
||||
|
||||
// The missile flag affects the bouncing mode.
|
||||
void SetMissile(AActor* info)
|
||||
{
|
||||
info->flags |= MF_MISSILE;
|
||||
if (info->BounceFlags & BOUNCE_DEH) info->BounceFlags = BOUNCE_Classic | BOUNCE_DEH;
|
||||
}
|
||||
|
||||
void ClearMissile(AActor* info)
|
||||
{
|
||||
info->flags &= ~MF_MISSILE;
|
||||
if (info->BounceFlags & BOUNCE_DEH) info->BounceFlags = BOUNCE_Grenade | BOUNCE_DEH;
|
||||
}
|
||||
|
||||
static FlagHandler flag1handlers[32] = {
|
||||
F(MF_SPECIAL),
|
||||
|
@ -3759,7 +3840,7 @@ static FlagHandler flag1handlers[32] = {
|
|||
F(MF_SLIDE),
|
||||
F(MF_FLOAT),
|
||||
F(MF_TELEPORT),
|
||||
F(MF_MISSILE),
|
||||
{ SetMissile, ClearMissile, [](AActor* a)->bool { return a->flags & MF_MISSILE; } },
|
||||
F(MF_DROPPED),
|
||||
F(MF_SHADOW),
|
||||
F(MF_NOBLOOD),
|
||||
|
@ -3769,7 +3850,12 @@ static FlagHandler flag1handlers[32] = {
|
|||
{ SetCountitem, ClearCountitem, [](AActor* a)->bool { return a->flags & MF_COUNTITEM; } },
|
||||
F(MF_SKULLFLY),
|
||||
F(MF_NOTDMATCH),
|
||||
// translation, unused and translucent are no longer checkable in any way. Pity.
|
||||
{ SetTranslation1, ClearTranslation1, CheckTranslation1 },
|
||||
{ SetTranslation2, ClearTranslation2, CheckTranslation2 },
|
||||
F6(MF6_TOUCHY),
|
||||
{ SetBounces, ClearBounces, [](AActor* a)->bool { return a->BounceFlags & BOUNCE_DEH; } },
|
||||
F(MF_FRIENDLY),
|
||||
{ SetTranslucent, ClearTranslucent, CheckTranslucent }
|
||||
};
|
||||
|
||||
static FlagHandler flag2handlers[32] = {
|
||||
|
|
|
@ -508,6 +508,7 @@ enum ActorBounceFlag
|
|||
BOUNCE_NotOnShootables = 1<<15, // do not bounce off shootable actors if we are a projectile. Explode instead.
|
||||
BOUNCE_BounceOnUnrips = 1<<16, // projectile bounces on actors with DONTRIP
|
||||
BOUNCE_NotOnSky = 1<<17, // Don't bounce on sky floors / ceilings / walls
|
||||
BOUNCE_DEH = 1<<18, // Flag was set through Dehacked.
|
||||
|
||||
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType | BOUNCE_MBF,
|
||||
|
||||
|
|
|
@ -207,4 +207,39 @@ inline bool P_IsBlockedByLine(AActor* actor, line_t* line)
|
|||
if ((actor->flags & MF_FLOAT) && (line->flags & ML_BLOCK_FLOATERS)) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// For Dehacked modified actors we need to dynamically check the bounce factors because MBF didn't bother to implement this properly and with other flags changing this must adjust.
|
||||
inline double GetMBFBounceFactor(AActor* actor)
|
||||
{
|
||||
if (actor->BounceFlags & BOUNCE_DEH) // only when modified through Dehacked.
|
||||
{
|
||||
constexpr double MBF_BOUNCE_NOGRAVITY = 1; // With NOGRAVITY: full momentum
|
||||
constexpr double MBF_BOUNCE_FLOATDROPOFF = 0.85; // With FLOAT and DROPOFF: 85%
|
||||
constexpr double MBF_BOUNCE_FLOAT = 0.7; // With FLOAT alone: 70%
|
||||
constexpr double MBF_BOUNCE_DEFAULT = 0.45; // Without the above flags: 45%
|
||||
|
||||
if (actor->flags & MF_NOGRAVITY) return MBF_BOUNCE_NOGRAVITY;
|
||||
if (actor->flags & MF_FLOAT) return (actor->flags & MF_DROPOFF) ? MBF_BOUNCE_FLOATDROPOFF : MBF_BOUNCE_FLOAT;
|
||||
return MBF_BOUNCE_DEFAULT;
|
||||
}
|
||||
return actor->bouncefactor;
|
||||
}
|
||||
|
||||
inline double GetWallBounceFactor(AActor* actor)
|
||||
{
|
||||
if (actor->BounceFlags & BOUNCE_DEH) // only when modified through Dehacked.
|
||||
{
|
||||
constexpr double MBF_BOUNCE_NOGRAVITY = 1; // With NOGRAVITY: full momentum
|
||||
constexpr double MBF_BOUNCE_WALL = 0.5; // Bouncing off walls: 50%
|
||||
return ((actor->flags & MF_NOGRAVITY) ? MBF_BOUNCE_NOGRAVITY : MBF_BOUNCE_WALL);
|
||||
}
|
||||
return actor->wallbouncefactor;
|
||||
}
|
||||
|
||||
// Yet another hack for MBF...
|
||||
inline bool CanJump(AActor* actor)
|
||||
{
|
||||
return (actor->flags6 & MF6_CANJUMP) || (
|
||||
(actor->BounceFlags & BOUNCE_MBF) && actor->IsSentient() && (actor->flags & MF_FLOAT));
|
||||
}
|
|
@ -445,7 +445,7 @@ int P_Move (AActor *actor)
|
|||
// want to yank them to the ground here as Doom did, since that makes
|
||||
// it difficult to thrust them vertically in a reasonable manner.
|
||||
// [GZ] Let jumping actors jump.
|
||||
if (!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
|
||||
if (!((actor->flags & MF_NOGRAVITY) || CanJump(actor))
|
||||
&& actor->Z() > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
|
||||
{
|
||||
return false;
|
||||
|
@ -558,7 +558,7 @@ int P_Move (AActor *actor)
|
|||
// to the floor if it is within MaxStepHeight, presuming that it is
|
||||
// actually walking down a step.
|
||||
if (try_ok &&
|
||||
!((actor->flags & MF_NOGRAVITY) || (actor->flags6 & MF6_CANJUMP))
|
||||
!((actor->flags & MF_NOGRAVITY) || CanJump(actor))
|
||||
&& actor->Z() > actor->floorz && !(actor->flags2 & MF2_ONMOBJ))
|
||||
{
|
||||
if (actor->Z() <= actor->floorz + actor->MaxStepHeight)
|
||||
|
@ -585,7 +585,7 @@ int P_Move (AActor *actor)
|
|||
|
||||
if (!try_ok)
|
||||
{
|
||||
if (((actor->flags6 & MF6_CANJUMP)||(actor->flags & MF_FLOAT)) && tm.floatok)
|
||||
if ((CanJump(actor) || (actor->flags & MF_FLOAT)) && tm.floatok)
|
||||
{ // must adjust height
|
||||
double savedz = actor->Z();
|
||||
|
||||
|
@ -596,7 +596,7 @@ int P_Move (AActor *actor)
|
|||
|
||||
|
||||
// [RH] Check to make sure there's nothing in the way of the float
|
||||
if (P_TestMobjZ (actor))
|
||||
if (P_TestMobjZ(actor))
|
||||
{
|
||||
actor->flags |= MF_INFLOAT;
|
||||
return true;
|
||||
|
|
|
@ -3486,7 +3486,7 @@ bool FSlide::BounceWall(AActor *mo)
|
|||
deltaangle = (lineangle * 2) - moveangle;
|
||||
mo->Angles.Yaw = deltaangle;
|
||||
|
||||
movelen = mo->Vel.XY().Length() * mo->wallbouncefactor;
|
||||
movelen = mo->Vel.XY().Length() * GetWallBounceFactor(mo);
|
||||
|
||||
FBoundingBox box(mo->X(), mo->Y(), mo->radius);
|
||||
if (BoxOnLineSide(box, line) == -1)
|
||||
|
@ -3573,7 +3573,7 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
|||
if (!ontop)
|
||||
{
|
||||
DAngle angle = BlockingMobj->AngleTo(mo) + ((pr_bounce() % 16) - 8);
|
||||
double speed = mo->VelXYToSpeed() * mo->wallbouncefactor; // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
double speed = mo->VelXYToSpeed() * GetWallBounceFactor(mo); // [GZ] was 0.75, using wallbouncefactor seems more consistent
|
||||
if (fabs(speed) < EQUAL_EPSILON) speed = 0;
|
||||
mo->Angles.Yaw = angle;
|
||||
mo->VelFromAngle(speed);
|
||||
|
@ -3595,7 +3595,7 @@ bool P_BounceActor(AActor *mo, AActor *BlockingMobj, bool ontop)
|
|||
}
|
||||
else
|
||||
{
|
||||
mo->Vel.Z *= mo->bouncefactor;
|
||||
mo->Vel.Z *= GetMBFBounceFactor(mo);
|
||||
}
|
||||
}
|
||||
else // Don't run through this for MBF-style bounces
|
||||
|
|
|
@ -1608,7 +1608,7 @@ bool AActor::FloorBounceMissile (secplane_t &plane)
|
|||
flags &= ~MF_INBOUNCE;
|
||||
return false;
|
||||
}
|
||||
else Vel.Z *= bouncefactor;
|
||||
else Vel.Z *= GetMBFBounceFactor(this);
|
||||
}
|
||||
else // Don't run through this for MBF-style bounces
|
||||
{
|
||||
|
@ -2551,7 +2551,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
if (mo->BounceFlags & BOUNCE_Floors)
|
||||
{
|
||||
mo->FloorBounceMissile (mo->floorsector->floorplane);
|
||||
/* if (!(mo->flags6 & MF6_CANJUMP)) */ return;
|
||||
/* if (!CanJump(mo)) */ return;
|
||||
}
|
||||
else if (mo->flags3 & MF3_NOEXPLODEFLOOR)
|
||||
{
|
||||
|
@ -2660,7 +2660,7 @@ void P_ZMovement (AActor *mo, double oldfloorz)
|
|||
if (mo->BounceFlags & BOUNCE_Ceilings)
|
||||
{ // ceiling bounce
|
||||
mo->FloorBounceMissile (mo->ceilingsector->ceilingplane);
|
||||
/*if (!(mo->flags6 & MF6_CANJUMP))*/ return;
|
||||
/* if (!CanJump(mo)) */ return;
|
||||
}
|
||||
if (mo->flags & MF_SKULLFLY)
|
||||
{ // the skull slammed into something
|
||||
|
|
Loading…
Reference in a new issue