diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 874ecbb51..5cce4c371 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -45,6 +45,7 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in m_IntensityX = intensityX; m_IntensityY = intensityY; m_IntensityZ = intensityZ; + m_CountdownStart = (double)duration; m_Countdown = duration; m_Flags = flags; } @@ -71,6 +72,14 @@ void DEarthquake::Serialize (FArchive &arc) { arc << m_IntensityY << m_IntensityZ << m_Flags; } + if (SaveVersion < 4520) + { + m_CountdownStart = 0; + } + else + { + arc << m_CountdownStart; + } } //========================================================================== @@ -91,7 +100,7 @@ void DEarthquake::Tick () Destroy (); return; } - + if (!S_IsActorPlayingSomething (m_Spot, CHAN_BODY, m_QuakeSFX)) { S_Sound (m_Spot, CHAN_BODY | CHAN_LOOP, m_QuakeSFX, 1, ATTN_NORM); @@ -131,6 +140,7 @@ void DEarthquake::Tick () } } } + if (--m_Countdown == 0) { if (S_IsActorPlayingSomething(m_Spot, CHAN_BODY, m_QuakeSFX)) @@ -150,15 +160,14 @@ void DEarthquake::Tick () // //========================================================================== -int DEarthquake::StaticGetQuakeIntensities(AActor *victim, - int &x, int &y, int &z, int &relx, int &rely, int &relz) +int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop) { if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) { return 0; } - - x = y = z = relx = rely = 0; + qprop.isScalingDown = qprop.isScalingUp = qprop.preferMaximum = qprop.fullIntensity = false; + qprop.intensityX = qprop.intensityY = qprop.intensityZ = qprop.relIntensityX = qprop.relIntensityY = qprop.relIntensityZ = 0; TThinkerIterator iterator(STAT_EARTHQUAKE); DEarthquake *quake; @@ -175,15 +184,28 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, ++count; if (quake->m_Flags & QF_RELATIVE) { - relx = MAX(relx, quake->m_IntensityX); - rely = MAX(rely, quake->m_IntensityY); - relz = MAX(relz, quake->m_IntensityZ); + qprop.relIntensityX = MAX(qprop.relIntensityX, quake->m_IntensityX); + qprop.relIntensityY = MAX(qprop.relIntensityY, quake->m_IntensityY); + qprop.relIntensityZ = MAX(qprop.relIntensityZ, quake->m_IntensityZ); } else { - x = MAX(x, quake->m_IntensityX); - y = MAX(y, quake->m_IntensityY); - z = MAX(z, quake->m_IntensityZ); + qprop.intensityX = MAX(qprop.intensityX, quake->m_IntensityX); + qprop.intensityY = MAX(qprop.intensityY, quake->m_IntensityY); + qprop.intensityZ = MAX(qprop.intensityZ, quake->m_IntensityZ); + } + if (quake->m_Flags) + { + qprop.scaleDownStart = quake->m_CountdownStart; + qprop.scaleDown = quake->m_Countdown; + qprop.isScalingDown = (quake->m_Flags & QF_SCALEDOWN) ? true : false; + qprop.isScalingUp = (quake->m_Flags & QF_SCALEUP) ? true : false; + qprop.preferMaximum = (quake->m_Flags & QF_MAX) ? true : false; + qprop.fullIntensity = (quake->m_Flags & QF_FULLINTENSITY) ? true : false; + } + else + { + qprop.scaleDownStart = qprop.scaleDown = 0.0; } } } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index e153f7070..00247c224 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -133,7 +133,18 @@ protected: enum { - QF_RELATIVE = 1, + QF_RELATIVE = 1, + QF_SCALEDOWN = 1 << 1, + QF_SCALEUP = 1 << 2, + QF_MAX = 1 << 3, + QF_FULLINTENSITY = 1 << 4, +}; + +struct quakeInfo +{ + int intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ; + double scaleDown, scaleDownStart; + bool isScalingDown, isScalingUp, preferMaximum, fullIntensity; }; class DEarthquake : public DThinker @@ -148,11 +159,12 @@ public: TObjPtr m_Spot; fixed_t m_TremorRadius, m_DamageRadius; int m_Countdown; + double m_CountdownStart; FSoundID m_QuakeSFX; int m_Flags; int m_IntensityX, m_IntensityY, m_IntensityZ; - static int StaticGetQuakeIntensities(AActor *viewer, int &x, int &y, int &z, int &relx, int &rely, int &relz); + static int StaticGetQuakeIntensities(AActor *viewer, quakeInfo &qprop); private: DEarthquake (); diff --git a/src/r_utility.cpp b/src/r_utility.cpp index a65c90d93..ebcff8af5 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -770,16 +770,45 @@ bool R_GetViewInterpolationStatus() // //========================================================================== -static fixed_t QuakePower(fixed_t factor, int intensity) +static fixed_t QuakePower(double factor, int intensity, quakeInfo quake) { + double scaleDownStart = quake.scaleDownStart; + double scaleDown = quake.scaleDown; if (intensity == 0) { return 0; } else { - return factor * ((pr_torchflicker() % (intensity << 2)) - (intensity << 1)); + double ss = (double)((pr_torchflicker() % (intensity << 2)) - (intensity << 1)); + double mtp = (quake.fullIntensity) ? 2.0 : 1.0; + if (quake.isScalingDown || quake.isScalingUp) + { + fixed_t result; + if (scaleDownStart == 0) scaleDownStart = 1; + + if (quake.isScalingDown && quake.isScalingUp) + { + if (quake.preferMaximum) + result = FLOAT2FIXED((factor * ss) * MAX(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart)); + else + result = FLOAT2FIXED((factor * ss) * MIN(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart)); + } + else if (quake.isScalingDown) + result = FLOAT2FIXED((factor * ss) * (scaleDown / scaleDownStart)); + else if (quake.isScalingUp) + result = FLOAT2FIXED((factor * ss) * ((scaleDownStart - scaleDown) / scaleDownStart)); + else + result = FLOAT2FIXED(factor * ss); + + return result; + } + else + { + return FLOAT2FIXED(factor * ss); + } } + } //========================================================================== @@ -892,40 +921,38 @@ void R_SetupFrame (AActor *actor) if (!paused) { - int intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ; - if (DEarthquake::StaticGetQuakeIntensities(camera, - intensityX, intensityY, intensityZ, - relIntensityX, relIntensityY, relIntensityZ) > 0) + quakeInfo quake; + if (DEarthquake::StaticGetQuakeIntensities(camera, quake) > 0) { - fixed_t quakefactor = FLOAT2FIXED(r_quakeintensity); + double quakefactor = r_quakeintensity; - if (relIntensityX != 0) + if (quake.relIntensityX != 0) { int ang = (camera->angle) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, relIntensityX); + fixed_t power = QuakePower(quakefactor, quake.relIntensityX, quake); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } - if (relIntensityY != 0) + if (quake.relIntensityY != 0) { int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, relIntensityY); + fixed_t power = QuakePower(quakefactor, quake.relIntensityY, quake); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } - if (intensityX != 0) + if (quake.intensityX != 0) { - viewx += QuakePower(quakefactor, intensityX); + viewx += QuakePower(quakefactor, quake.intensityX, quake); } - if (intensityY != 0) + if (quake.intensityY != 0) { - viewy += QuakePower(quakefactor, intensityY); + viewy += QuakePower(quakefactor, quake.intensityY, quake); } // FIXME: Relative Z is not relative - intensityZ = MAX(intensityZ, relIntensityZ); - if (intensityZ != 0) + quake.intensityZ = MAX(quake.intensityZ, quake.relIntensityZ); + if (quake.intensityZ != 0) { - viewz += QuakePower(quakefactor, intensityZ); + viewz += QuakePower(quakefactor, quake.intensityZ, quake); } } } diff --git a/src/version.h b/src/version.h index 8a73d6d6d..3405a3920 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4519 +#define SAVEVER 4520 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x) diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 3df42e0f8..78149430a 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -461,7 +461,11 @@ enum // Flags for A_QuakeEx enum { - QF_RELATIVE = 1, + QF_RELATIVE = 1, + QF_SCALEDOWN = 1 << 1, + QF_SCALEUP = 1 << 2, + QF_MAX = 1 << 3, + QF_FULLINTENSITY = 1 << 4, }; // This is only here to provide one global variable for testing. diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 58240440d..f84c3ceff 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1276,42 +1276,60 @@ OptionMenu "CompatibilityOptions" { Title "COMPATIBILITY OPTIONS" Option "Compatibility mode", "compatmode", "CompatModes", "", 1 + StaticText " " + StaticText "Actor Behavior",1 + Option "Crushed monsters can be resurrected", "compat_CORPSEGIBS", "YesNo" + Option "Friendly monsters aren't blocked", "compat_NOBLOCKFRIENDS", "YesNo" + Option "Limit Pain Elementals' Lost Souls", "compat_LIMITPAIN", "YesNo" + Option "Monster movement is affected by effects", "compat_MBFMONSTERMOVE", "YesNo" + Option "Monsters cannot cross dropoffs", "compat_CROSSDROPOFF", "YesNo" + Option "Monsters get stuck over dropoffs", "compat_DROPOFF", "YesNo" + Option "Monsters see invisible players", "compat_INVISIBILITY", "YesNo" + Option "No Minotaur floor flames in water", "compat_MINOTAUR", "YesNo" + Option "Spawn item drops on the floor", "compat_NOTOSSDROPS", "YesNo" + + StaticText " " + StaticText "DehackEd Behavior",1 + Option "DEH health settings like Doom2.exe", "compat_DEHHEALTH", "YesNo" + Option "Original A_Mushroom speed in DEH mods", "compat_MUSHROOM", "YesNo" + + StaticText " " + StaticText "Map/Action Behavior",1 + Option "All special lines can block ", "compat_USEBLOCKING", "YesNo" + Option "Allow any bossdeath for level special", "compat_ANYBOSSDEATH", "YesNo" + Option "Disable BOOM door light effect", "compat_NODOORLIGHT", "YesNo" + Option "Find neighboring light like Doom", "compat_LIGHT", "YesNo" Option "Find shortest textures like Doom", "compat_SHORTTEX", "YesNo" Option "Use buggier stair building", "compat_stairs", "YesNo" - Option "Find neighboring light like Doom", "compat_LIGHT", "YesNo" - Option "Limit Pain Elementals' Lost Souls", "compat_LIMITPAIN", "YesNo" - Option "Don't let others hear your pickups", "compat_SILENTPICKUP", "YesNo" + Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo" + + StaticText " " + StaticText "Physics Behavior",1 Option "Actors are infinitely tall", "compat_nopassover", "YesNo" - Option "Enable wall running", "compat_WALLRUN", "YesNo" - Option "Spawn item drops on the floor", "compat_NOTOSSDROPS", "YesNo" - Option "All special lines can block ", "compat_USEBLOCKING", "YesNo" - Option "Disable BOOM door light effect", "compat_NODOORLIGHT", "YesNo" - Option "Raven scrollers use original speed", "compat_RAVENSCROLL", "YesNo" - Option "Use original sound target handling", "compat_SOUNDTARGET", "YesNo" - Option "DEH health settings like Doom2.exe", "compat_DEHHEALTH", "YesNo" - Option "Self ref. sectors don't block shots", "compat_TRACE", "YesNo" - Option "Monsters get stuck over dropoffs", "compat_DROPOFF", "YesNo" - Option "Monsters cannot cross dropoffs", "compat_CROSSDROPOFF", "YesNo" - Option "Monsters see invisible players", "compat_INVISIBILITY", "YesNo" Option "Boom scrollers are additive", "compat_BOOMSCROLL", "YesNo" - Option "Inst. moving floors are not silent", "compat_silentinstantfloors", "YesNo" - Option "Sector sounds use center as source", "compat_SECTORSOUNDS", "YesNo" - Option "Use Doom heights for missile clipping", "compat_MISSILECLIP", "YesNo" - Option "Allow any bossdeath for level special", "compat_ANYBOSSDEATH", "YesNo" - Option "No Minotaur floor flames in water", "compat_MINOTAUR", "YesNo" - Option "Original A_Mushroom speed in DEH mods", "compat_MUSHROOM", "YesNo" - Option "Monster movement is affected by effects", "compat_MBFMONSTERMOVE", "YesNo" - Option "Crushed monsters can be resurrected", "compat_CORPSEGIBS", "YesNo" - Option "Friendly monsters aren't blocked", "compat_NOBLOCKFRIENDS", "YesNo" - Option "Invert sprite sorting", "compat_SPRITESORT", "YesNo" + Option "Cannot travel straight NSEW", "compat_badangles", "YesNo" + Option "Enable wall running", "compat_WALLRUN", "YesNo" + Option "Raven scrollers use original speed", "compat_RAVENSCROLL", "YesNo" + Option "Self ref. sectors don't block shots", "compat_TRACE", "YesNo" Option "Use Doom code for hitscan checks", "compat_HITSCAN", "YesNo" - Option "Cripple sound for silent BFG trick", "compat_soundslots", "YesNo" + Option "Use Doom heights for missile clipping", "compat_MISSILECLIP", "YesNo" + + + StaticText " " + StaticText "Rendering Behavior",1 Option "Draw polyobjects like Hexen", "compat_POLYOBJ", "YesNo" Option "Ignore Y offsets on masked midtextures", "compat_MASKEDMIDTEX", "YesNo" - Option "Cannot travel straight NSEW", "compat_badangles", "YesNo" - Option "Use Doom's floor motion behavior", "compat_floormove", "YesNo" + Option "Invert sprite sorting", "compat_SPRITESORT", "YesNo" + + StaticText " " + StaticText "Sound Behavior",1 + Option "Cripple sound for silent BFG trick", "compat_soundslots", "YesNo" + Option "Don't let others hear your pickups", "compat_SILENTPICKUP", "YesNo" + Option "Inst. moving floors are not silent", "compat_silentinstantfloors", "YesNo" + Option "Sector sounds use center as source", "compat_SECTORSOUNDS", "YesNo" Option "Sounds stop when actor vanishes", "compat_soundcutoff", "YesNo" + Option "Use original sound target handling", "compat_SOUNDTARGET", "YesNo" Class "CompatibilityMenu" }