From 7050d03222a239cf70ead2dad6d93180e1d278f7 Mon Sep 17 00:00:00 2001 From: MajorCooke Date: Sat, 14 Feb 2015 15:58:39 -0600 Subject: [PATCH 1/2] Added A_QuakeEx(intensity x, y, z, duration, damrad, tremrad, sound, flags) - Unlocks the full potential of using quakes, including the Z axis. Each intensity applies to X/Y/Z planes whenever a player is experiencing it. - Flags: - QF_RELATIVE - Adjusts the quaking of the camera to go in the direction its aiming (X: forward/backward. Y: Left/right.) - Plans for including pitch will be implemented in the future for the Z axis with relativity. --- src/g_shared/a_quake.cpp | 86 +++++++++++++++++++++++++----- src/g_shared/a_sharedglobal.h | 14 +++-- src/p_spec.h | 3 +- src/r_utility.cpp | 32 +++++++++-- src/thingdef/thingdef_codeptr.cpp | 22 ++++++++ wadsrc/static/actors/actor.txt | 1 + wadsrc/static/actors/constants.txt | 5 ++ 7 files changed, 143 insertions(+), 20 deletions(-) diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index c3a227b36..462deafb6 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -33,8 +33,8 @@ DEarthquake::DEarthquake() // //========================================================================== -DEarthquake::DEarthquake (AActor *center, int intensity, int duration, - int damrad, int tremrad, FSoundID quakesound) +DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int intensityZ, int duration, + int damrad, int tremrad, FSoundID quakesound, int flags) : DThinker(STAT_EARTHQUAKE) { m_QuakeSFX = quakesound; @@ -42,8 +42,12 @@ DEarthquake::DEarthquake (AActor *center, int intensity, int duration, // Radii are specified in tile units (64 pixels) m_DamageRadius = damrad << (FRACBITS); m_TremorRadius = tremrad << (FRACBITS); - m_Intensity = intensity; + m_Intensity = intensityX; m_Countdown = duration; + m_Flags = flags; + m_iX = intensityX; + m_iY = intensityY; + m_iZ = intensityZ; } //========================================================================== @@ -54,10 +58,10 @@ DEarthquake::DEarthquake (AActor *center, int intensity, int duration, void DEarthquake::Serialize (FArchive &arc) { - Super::Serialize (arc); + Super::Serialize (arc); //[MC] m_Intensity is unused now but I don't want to break compatibility... arc << m_Spot << m_Intensity << m_Countdown << m_TremorRadius << m_DamageRadius - << m_QuakeSFX; + << m_QuakeSFX << m_Flags << m_iX << m_iY << m_iZ; } //========================================================================== @@ -126,9 +130,10 @@ void DEarthquake::Tick () // //========================================================================== -int DEarthquake::StaticGetQuakeIntensity (AActor *victim) +int DEarthquake::StaticGetQuakeIntensity (AActor *victim, int selector) { int intensity = 0; + int quakeIntensity = 0; TThinkerIterator iterator (STAT_EARTHQUAKE); DEarthquake *quake; @@ -145,32 +150,84 @@ int DEarthquake::StaticGetQuakeIntensity (AActor *victim) victim->y - quake->m_Spot->y); if (dist < quake->m_TremorRadius) { - if (intensity < quake->m_Intensity) - intensity = quake->m_Intensity; + switch (selector) + { + default: + case 0: + quakeIntensity = quake->m_iX; + break; + case 1: + quakeIntensity = quake->m_iY; + break; + case 2: + quakeIntensity = quake->m_iZ; + break; + + } + + if (intensity < quakeIntensity) + intensity = quakeIntensity; } } } return intensity; } +//========================================================================== +// +// DEarthquake::StaticGetQuakeIntensity +// +// Searches for all quakes near the victim and returns their combined +// intensity. +// +//========================================================================== + +int DEarthquake::StaticGetQuakeFlags(AActor *victim) +{ + int flags = 0; + TThinkerIterator iterator(STAT_EARTHQUAKE); + DEarthquake *quake; + + if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) + { + return 0; + } + + while ((quake = iterator.Next()) != NULL) + { + if (quake->m_Spot != NULL) + { + fixed_t dist = P_AproxDistance(victim->x - quake->m_Spot->x, + victim->y - quake->m_Spot->y); + if (dist < quake->m_TremorRadius) + { + if (!(flags & QF_RELATIVE) && (quake->m_Flags & QF_RELATIVE)) + flags += QF_RELATIVE; + } + } + } + return flags; +} //========================================================================== // // P_StartQuake // //========================================================================== -bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) +bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags) { AActor *center; bool res = false; - intensity = clamp (intensity, 1, 9); + if (intensityX) intensityX = clamp(intensityX, 1, 9); + if (intensityY) intensityY = clamp(intensityY, 1, 9); + if (intensityZ) intensityZ = clamp(intensityZ, 1, 9); if (tid == 0) { if (activator != NULL) { - new DEarthquake(activator, intensity, duration, damrad, tremrad, quakesfx); + new DEarthquake(activator, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags); return true; } } @@ -180,9 +237,14 @@ bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int while ( (center = iterator.Next ()) ) { res = true; - new DEarthquake (center, intensity, duration, damrad, tremrad, quakesfx); + new DEarthquake(center, intensityX, intensityY, intensityZ, duration, damrad, tremrad, quakesfx, flags); } } return res; } + +bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx) +{ //Maintains original behavior by passing 0 to intensityZ, and flags. + return P_StartQuakeXYZ(activator, tid, intensity, intensity, 0, duration, damrad, tremrad, quakesfx, 0); +} diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index a898433f0..a186fa010 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -131,23 +131,31 @@ protected: DFlashFader (); }; +enum +{ + QF_RELATIVE = 1, +}; + class DEarthquake : public DThinker { DECLARE_CLASS (DEarthquake, DThinker) HAS_OBJECT_POINTERS public: - DEarthquake (AActor *center, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); + DEarthquake(AActor *center, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags); void Serialize (FArchive &arc); void Tick (); - TObjPtr m_Spot; fixed_t m_TremorRadius, m_DamageRadius; int m_Intensity; int m_Countdown; FSoundID m_QuakeSFX; + int m_Flags; + int m_iX, m_iY, m_iZ; - static int StaticGetQuakeIntensity (AActor *viewer); + static int StaticGetQuakeFlags(AActor *viewer); + static int StaticGetQuakeIntensity (AActor *viewer, int selector); + private: DEarthquake (); diff --git a/src/p_spec.h b/src/p_spec.h index 0d7ef4cff..2edfe6390 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -929,6 +929,7 @@ void P_DoDeferedScripts (void); // // [RH] p_quake.c // -bool P_StartQuake (AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); +bool P_StartQuakeXYZ(AActor *activator, int tid, int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, FSoundID quakesfx, int flags); +bool P_StartQuake(AActor *activator, int tid, int intensity, int duration, int damrad, int tremrad, FSoundID quakesfx); #endif diff --git a/src/r_utility.cpp b/src/r_utility.cpp index 585e3dcf3..f809a6800 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -875,13 +875,37 @@ void R_SetupFrame (AActor *actor) if (!paused) { - int intensity = DEarthquake::StaticGetQuakeIntensity (camera); - if (intensity != 0) + int intensityX = DEarthquake::StaticGetQuakeIntensity(camera, 0); + int intensityY = DEarthquake::StaticGetQuakeIntensity(camera, 1); + int intensityZ = DEarthquake::StaticGetQuakeIntensity(camera, 2); + int quakeflags = DEarthquake::StaticGetQuakeFlags(camera); + if (intensityX || intensityY || intensityZ) { fixed_t quakefactor = FLOAT2FIXED(r_quakeintensity); - viewx += quakefactor * ((pr_torchflicker() % (intensity<<2)) - (intensity<<1)); - viewy += quakefactor * ((pr_torchflicker() % (intensity<<2)) - (intensity<<1)); + if ((quakeflags & QF_RELATIVE) && (intensityX != intensityY)) + { + if (intensityX) + { + int ang = (camera->angle) >> ANGLETOFINESHIFT; + int tflicker = pr_torchflicker(); + viewx += FixedMul(finecosine[ang], (quakefactor * ((tflicker % (intensityX << 2)) - (intensityX << 1)))); + viewy += FixedMul(finesine[ang], (quakefactor * ((tflicker % (intensityX << 2)) - (intensityX << 1)))); + } + if (intensityY) + { + int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; + int tflicker = pr_torchflicker(); + viewx += FixedMul(finecosine[ang], (quakefactor * ((tflicker % (intensityY << 2)) - (intensityY << 1)))); + viewy += FixedMul(finesine[ang], (quakefactor * ((tflicker % (intensityY << 2)) - (intensityY << 1)))); + } + } + else + { + if (intensityX) viewx += quakefactor * ((pr_torchflicker() % (intensityX << 2)) - (intensityX << 1)); + if (intensityY) viewy += quakefactor * ((pr_torchflicker() % (intensityY << 2)) - (intensityY << 1)); + } + if (intensityZ) viewz += quakefactor * ((pr_torchflicker() % (intensityZ << 2)) - (intensityZ << 1)); } } diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index fc157c92b..280f09fd6 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -4403,6 +4403,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Quake) P_StartQuake(self, 0, intensity, duration, damrad, tremrad, sound); } +//=========================================================================== +// +// A_QuakeEx +// +// Extended version of A_Quake. Takes individual axis into account and can +// take a flag. +//=========================================================================== + +DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_QuakeEx) +{ + ACTION_PARAM_START(8); + ACTION_PARAM_INT(intensityX, 0); + ACTION_PARAM_INT(intensityY, 1); + ACTION_PARAM_INT(intensityZ, 2); + ACTION_PARAM_INT(duration, 3); + ACTION_PARAM_INT(damrad, 4); + ACTION_PARAM_INT(tremrad, 5); + ACTION_PARAM_SOUND(sound, 6); + ACTION_PARAM_INT(flags, 7); + P_StartQuakeXYZ(self, 0, intensityX, intensityY, intensityZ, duration, damrad, tremrad, sound, flags); +} + //=========================================================================== // // A_Weave diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index c03c86596..e8906af3f 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -299,6 +299,7 @@ ACTOR Actor native //: Thinker action native A_SetUserArray(name varname, int index, int value); action native A_SetSpecial(int spec, int arg0 = 0, int arg1 = 0, int arg2 = 0, int arg3 = 0, int arg4 = 0); action native A_Quake(int intensity, int duration, int damrad, int tremrad, sound sfx = "world/quake"); + action native A_QuakeEx(int intensityX, int intensityY, int intensityZ, int duration, int damrad, int tremrad, sound sfx = "world/quake", int flags = 0); action native A_SetTics(int tics); action native A_SetDamageType(name damagetype); action native A_DropItem(class item, int dropamount = -1, int chance = 256); diff --git a/wadsrc/static/actors/constants.txt b/wadsrc/static/actors/constants.txt index 1604b5c83..b3fd26ecb 100644 --- a/wadsrc/static/actors/constants.txt +++ b/wadsrc/static/actors/constants.txt @@ -457,6 +457,11 @@ enum FAF_NODISTFACTOR = 8, }; +// Flags for A_QuakeEx +enum +{ + QF_RELATIVE = 1, +}; // This is only here to provide one global variable for testing. native int testglobalvar; From e377c2c4f867dbcbb701ba97384277ff9b3d1869 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Wed, 18 Feb 2015 14:48:52 -0600 Subject: [PATCH 2/2] Change XYZ Quaking from Major Cooke - Relative quakes are different from other quakes; all quakes affecting the camera do not become relative if one of them is relative. - Use a single function call to get quake visual parameters instead of four. - Thrust things in a psuedo-ellipse if they're inside a damaging quake whose IntensityX != IntensityY. - Don't break old savegames. --- src/g_shared/a_quake.cpp | 113 +++++++++++++++------------------- src/g_shared/a_sharedglobal.h | 7 +-- src/r_utility.cpp | 69 +++++++++++++-------- src/version.h | 2 +- 4 files changed, 96 insertions(+), 95 deletions(-) diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 462deafb6..874ecbb51 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -42,12 +42,11 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in // Radii are specified in tile units (64 pixels) m_DamageRadius = damrad << (FRACBITS); m_TremorRadius = tremrad << (FRACBITS); - m_Intensity = intensityX; + m_IntensityX = intensityX; + m_IntensityY = intensityY; + m_IntensityZ = intensityZ; m_Countdown = duration; m_Flags = flags; - m_iX = intensityX; - m_iY = intensityY; - m_iZ = intensityZ; } //========================================================================== @@ -58,10 +57,20 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in void DEarthquake::Serialize (FArchive &arc) { - Super::Serialize (arc); //[MC] m_Intensity is unused now but I don't want to break compatibility... - arc << m_Spot << m_Intensity << m_Countdown + Super::Serialize (arc); + arc << m_Spot << m_IntensityX << m_Countdown << m_TremorRadius << m_DamageRadius - << m_QuakeSFX << m_Flags << m_iX << m_iY << m_iZ; + << m_QuakeSFX; + if (SaveVersion < 4519) + { + m_IntensityY = m_IntensityX; + m_IntensityZ = 0; + m_Flags = 0; + } + else + { + arc << m_IntensityY << m_IntensityZ << m_Flags; + } } //========================================================================== @@ -106,7 +115,18 @@ void DEarthquake::Tick () } // Thrust player around angle_t an = victim->angle + ANGLE_1*pr_quake(); - P_ThrustMobj (victim, an, m_Intensity << (FRACBITS-1)); + if (m_IntensityX == m_IntensityY) + { // Thrust in a circle + P_ThrustMobj (victim, an, m_IntensityX << (FRACBITS-1)); + } + else + { // Thrust in an ellipse + an >>= ANGLETOFINESHIFT; + // So this is actually completely wrong, but it ought to be good + // enough. Otherwise, I'd have to use tangents and square roots. + victim->velx += FixedMul(m_IntensityX << (FRACBITS-1), finecosine[an]); + victim->vely += FixedMul(m_IntensityY << (FRACBITS-1), finesine[an]); + } } } } @@ -130,18 +150,20 @@ void DEarthquake::Tick () // //========================================================================== -int DEarthquake::StaticGetQuakeIntensity (AActor *victim, int selector) +int DEarthquake::StaticGetQuakeIntensities(AActor *victim, + int &x, int &y, int &z, int &relx, int &rely, int &relz) { - int intensity = 0; - int quakeIntensity = 0; - TThinkerIterator iterator (STAT_EARTHQUAKE); - DEarthquake *quake; - if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) { return 0; } + x = y = z = relx = rely = 0; + + TThinkerIterator iterator(STAT_EARTHQUAKE); + DEarthquake *quake; + int count = 0; + while ( (quake = iterator.Next()) != NULL) { if (quake->m_Spot != NULL) @@ -150,64 +172,25 @@ int DEarthquake::StaticGetQuakeIntensity (AActor *victim, int selector) victim->y - quake->m_Spot->y); if (dist < quake->m_TremorRadius) { - switch (selector) + ++count; + if (quake->m_Flags & QF_RELATIVE) { - default: - case 0: - quakeIntensity = quake->m_iX; - break; - case 1: - quakeIntensity = quake->m_iY; - break; - case 2: - quakeIntensity = quake->m_iZ; - break; - + relx = MAX(relx, quake->m_IntensityX); + rely = MAX(rely, quake->m_IntensityY); + relz = MAX(relz, quake->m_IntensityZ); + } + else + { + x = MAX(x, quake->m_IntensityX); + y = MAX(y, quake->m_IntensityY); + z = MAX(z, quake->m_IntensityZ); } - - if (intensity < quakeIntensity) - intensity = quakeIntensity; } } } - return intensity; + return count; } -//========================================================================== -// -// DEarthquake::StaticGetQuakeIntensity -// -// Searches for all quakes near the victim and returns their combined -// intensity. -// -//========================================================================== - -int DEarthquake::StaticGetQuakeFlags(AActor *victim) -{ - int flags = 0; - TThinkerIterator iterator(STAT_EARTHQUAKE); - DEarthquake *quake; - - if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) - { - return 0; - } - - while ((quake = iterator.Next()) != NULL) - { - if (quake->m_Spot != NULL) - { - fixed_t dist = P_AproxDistance(victim->x - quake->m_Spot->x, - victim->y - quake->m_Spot->y); - if (dist < quake->m_TremorRadius) - { - if (!(flags & QF_RELATIVE) && (quake->m_Flags & QF_RELATIVE)) - flags += QF_RELATIVE; - } - } - } - return flags; -} //========================================================================== // // P_StartQuake diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index a186fa010..e153f7070 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -147,15 +147,12 @@ public: void Tick (); TObjPtr m_Spot; fixed_t m_TremorRadius, m_DamageRadius; - int m_Intensity; int m_Countdown; FSoundID m_QuakeSFX; int m_Flags; - int m_iX, m_iY, m_iZ; + int m_IntensityX, m_IntensityY, m_IntensityZ; - static int StaticGetQuakeFlags(AActor *viewer); - static int StaticGetQuakeIntensity (AActor *viewer, int selector); - + static int StaticGetQuakeIntensities(AActor *viewer, int &x, int &y, int &z, int &relx, int &rely, int &relz); private: DEarthquake (); diff --git a/src/r_utility.cpp b/src/r_utility.cpp index f809a6800..a65c90d93 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -764,6 +764,23 @@ bool R_GetViewInterpolationStatus() return NoInterpolateView; } +//========================================================================== +// +// QuakePower +// +//========================================================================== + +static fixed_t QuakePower(fixed_t factor, int intensity) +{ + if (intensity == 0) + { + return 0; + } + else + { + return factor * ((pr_torchflicker() % (intensity << 2)) - (intensity << 1)); + } +} //========================================================================== // @@ -875,37 +892,41 @@ void R_SetupFrame (AActor *actor) if (!paused) { - int intensityX = DEarthquake::StaticGetQuakeIntensity(camera, 0); - int intensityY = DEarthquake::StaticGetQuakeIntensity(camera, 1); - int intensityZ = DEarthquake::StaticGetQuakeIntensity(camera, 2); - int quakeflags = DEarthquake::StaticGetQuakeFlags(camera); - if (intensityX || intensityY || intensityZ) + int intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ; + if (DEarthquake::StaticGetQuakeIntensities(camera, + intensityX, intensityY, intensityZ, + relIntensityX, relIntensityY, relIntensityZ) > 0) { fixed_t quakefactor = FLOAT2FIXED(r_quakeintensity); - if ((quakeflags & QF_RELATIVE) && (intensityX != intensityY)) + if (relIntensityX != 0) { - if (intensityX) - { - int ang = (camera->angle) >> ANGLETOFINESHIFT; - int tflicker = pr_torchflicker(); - viewx += FixedMul(finecosine[ang], (quakefactor * ((tflicker % (intensityX << 2)) - (intensityX << 1)))); - viewy += FixedMul(finesine[ang], (quakefactor * ((tflicker % (intensityX << 2)) - (intensityX << 1)))); - } - if (intensityY) - { - int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; - int tflicker = pr_torchflicker(); - viewx += FixedMul(finecosine[ang], (quakefactor * ((tflicker % (intensityY << 2)) - (intensityY << 1)))); - viewy += FixedMul(finesine[ang], (quakefactor * ((tflicker % (intensityY << 2)) - (intensityY << 1)))); - } + int ang = (camera->angle) >> ANGLETOFINESHIFT; + fixed_t power = QuakePower(quakefactor, relIntensityX); + viewx += FixedMul(finecosine[ang], power); + viewy += FixedMul(finesine[ang], power); } - else + if (relIntensityY != 0) { - if (intensityX) viewx += quakefactor * ((pr_torchflicker() % (intensityX << 2)) - (intensityX << 1)); - if (intensityY) viewy += quakefactor * ((pr_torchflicker() % (intensityY << 2)) - (intensityY << 1)); + int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; + fixed_t power = QuakePower(quakefactor, relIntensityY); + viewx += FixedMul(finecosine[ang], power); + viewy += FixedMul(finesine[ang], power); + } + if (intensityX != 0) + { + viewx += QuakePower(quakefactor, intensityX); + } + if (intensityY != 0) + { + viewy += QuakePower(quakefactor, intensityY); + } + // FIXME: Relative Z is not relative + intensityZ = MAX(intensityZ, relIntensityZ); + if (intensityZ != 0) + { + viewz += QuakePower(quakefactor, intensityZ); } - if (intensityZ) viewz += quakefactor * ((pr_torchflicker() % (intensityZ << 2)) - (intensityZ << 1)); } } diff --git a/src/version.h b/src/version.h index 09b830438..2be4787ee 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 4518 +#define SAVEVER 4519 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)