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;