From 15f30886cdc838ae06e60343adb275f1764cd2ef Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 3 Jan 2017 20:06:20 +0100 Subject: [PATCH] - scriptified the TimeFreezer powerup. --- src/g_inventory/a_artifacts.cpp | 128 ---------------------- src/g_level.cpp | 1 + src/s_sound.cpp | 17 +++ wadsrc/static/zscript/base.txt | 3 + wadsrc/static/zscript/shared/powerups.txt | 123 ++++++++++++++++++++- 5 files changed, 143 insertions(+), 129 deletions(-) diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 335565efd..4bd1b67d5 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -1481,134 +1481,6 @@ void APowerBuddha::EndEffect () Owner->player->cheats &= ~CF_BUDDHA; } -// Time freezer powerup ----------------------------------------------------- - -IMPLEMENT_CLASS( APowerTimeFreezer, false, false) - -//=========================================================================== -// -// APowerTimeFreezer :: InitEffect -// -//=========================================================================== - -void APowerTimeFreezer::InitEffect() -{ - int freezemask; - - Super::InitEffect(); - - if (Owner == NULL || Owner->player == NULL) - return; - - // When this powerup is in effect, pause the music. - S_PauseSound(false, false); - - // Give the player and his teammates the power to move when time is frozen. - freezemask = 1 << (Owner->player - players); - Owner->player->timefreezer |= freezemask; - for (int i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i] && - players[i].mo != NULL && - players[i].mo->IsTeammate(Owner) - ) - { - players[i].timefreezer |= freezemask; - } - } - - // [RH] The effect ends one tic after the counter hits zero, so make - // sure we start at an odd count. - EffectTics += !(EffectTics & 1); - if ((EffectTics & 1) == 0) - { - EffectTics++; - } - // Make sure the effect starts and ends on an even tic. - if ((level.time & 1) == 0) - { - level.flags2 |= LEVEL2_FROZEN; - } - else - { - // Compensate for skipped tic, but beware of overflow. - if(EffectTics < INT_MAX) - EffectTics++; - } -} - -//=========================================================================== -// -// APowerTimeFreezer :: DoEffect -// -//=========================================================================== - -void APowerTimeFreezer::DoEffect() -{ - Super::DoEffect(); - // [RH] Do not change LEVEL_FROZEN on odd tics, or the Revenant's tracer - // will get thrown off. - // [ED850] Don't change it if the player is predicted either. - if (level.time & 1 || (Owner != NULL && Owner->player != NULL && Owner->player->cheats & CF_PREDICTING)) - { - return; - } - // [RH] The "blinking" can't check against EffectTics exactly or it will - // never happen, because InitEffect ensures that EffectTics will always - // be odd when level.time is even. - if ( EffectTics > 4*32 - || (( EffectTics > 3*32 && EffectTics <= 4*32 ) && ((EffectTics + 1) & 15) != 0 ) - || (( EffectTics > 2*32 && EffectTics <= 3*32 ) && ((EffectTics + 1) & 7) != 0 ) - || (( EffectTics > 32 && EffectTics <= 2*32 ) && ((EffectTics + 1) & 3) != 0 ) - || (( EffectTics > 0 && EffectTics <= 1*32 ) && ((EffectTics + 1) & 1) != 0 )) - level.flags2 |= LEVEL2_FROZEN; - else - level.flags2 &= ~LEVEL2_FROZEN; -} - -//=========================================================================== -// -// APowerTimeFreezer :: EndEffect -// -//=========================================================================== - -void APowerTimeFreezer::EndEffect() -{ - int i; - - Super::EndEffect(); - - // If there is an owner, remove the timefreeze flag corresponding to - // her from all players. - if (Owner != NULL && Owner->player != NULL) - { - int freezemask = ~(1 << (Owner->player - players)); - for (i = 0; i < MAXPLAYERS; ++i) - { - players[i].timefreezer &= freezemask; - } - } - - // Are there any players who still have timefreezer bits set? - for (i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].timefreezer != 0) - { - break; - } - } - - if (i == MAXPLAYERS) - { - // No, so allow other actors to move about freely once again. - level.flags2 &= ~LEVEL2_FROZEN; - - // Also, turn the music back on. - S_ResumeSound(false); - } -} - - // Morph powerup ------------------------------------------------------ IMPLEMENT_CLASS(APowerMorph, false, true) diff --git a/src/g_level.cpp b/src/g_level.cpp index e6d1618bf..6865607d5 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1888,6 +1888,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLI DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE) DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND) DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS) +DEFINE_FIELD_BIT(FLevelLocals, flags2, frozen, LEVEL2_FROZEN) //========================================================================== // diff --git a/src/s_sound.cpp b/src/s_sound.cpp index be1b572f1..a37182e20 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1852,6 +1852,15 @@ void S_PauseSound (bool notmusic, bool notsfx) } } +DEFINE_ACTION_FUNCTION(DObject, S_PauseSound) +{ + PARAM_PROLOGUE; + PARAM_BOOL(notmusic); + PARAM_BOOL(notsfx); + S_PauseSound(notmusic, notsfx); + return 0; +} + //========================================================================== // // S_ResumeSound @@ -1873,6 +1882,14 @@ void S_ResumeSound (bool notsfx) } } +DEFINE_ACTION_FUNCTION(DObject, S_ResumeSound) +{ + PARAM_PROLOGUE; + PARAM_BOOL(notsfx); + S_ResumeSound(notsfx); + return 0; +} + //========================================================================== // // S_SetSoundPaused diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index e609610e6..38fa79b76 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -9,6 +9,8 @@ class Object native native static vector3, int G_PickPlayerStart(int pnum, int flags = 0); native static int GameType(); native static void S_Sound (Sound sound_id, int channel, float volume = 1, float attenuation = ATTN_NORM); + native static void S_PauseSound (bool notmusic, bool notsfx); + native static void S_ResumeSound (bool notsfx); native static bool S_ChangeMusic(String music_name, int order = 0, bool looping = true, bool force = false); native static void C_MidPrint(string fontname, string textlabel, bool bold = false); // always uses the stringtable. native static uint BAM(double angle); @@ -138,6 +140,7 @@ struct LevelLocals native native bool checkswitchrange; native bool polygrind; native bool nomonsters; + native bool frozen; // level_info_t *info cannot be done yet. } diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index 1ef333f60..e653cb275 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -228,12 +228,133 @@ class PowerScanner : Powerup } } -class PowerTimeFreezer : Powerup native +//=========================================================================== +// +// TimeFreezer +// +//=========================================================================== + +class PowerTimeFreezer : Powerup { Default { Powerup.Duration -12; } + + //=========================================================================== + // + // InitEffect + // + //=========================================================================== + + override void InitEffect() + { + int freezemask; + + Super.InitEffect(); + + if (Owner == null || Owner.player == null) + return; + + // When this powerup is in effect, pause the music. + S_PauseSound(false, false); + + // Give the player and his teammates the power to move when time is frozen. + freezemask = 1 << Owner.PlayerNumber(); + Owner.player.timefreezer |= freezemask; + for (int i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] && + players[i].mo != null && + players[i].mo.IsTeammate(Owner) + ) + { + players[i].timefreezer |= freezemask; + } + } + + // [RH] The effect ends one tic after the counter hits zero, so make + // sure we start at an odd count. + EffectTics += !(EffectTics & 1); + if ((EffectTics & 1) == 0) + { + EffectTics++; + } + // Make sure the effect starts and ends on an even tic. + if ((level.time & 1) == 0) + { + level.frozen = true;; + } + else + { + // Compensate for skipped tic, but beware of overflow. + if(EffectTics < 0x7fffffff) + EffectTics++; + } + } + + //=========================================================================== + // + // APowerTimeFreezer :: DoEffect + // + //=========================================================================== + + override void DoEffect() + { + Super.DoEffect(); + // [RH] Do not change LEVEL_FROZEN on odd tics, or the Revenant's tracer + // will get thrown off. + // [ED850] Don't change it if the player is predicted either. + if (level.time & 1 || (Owner != null && Owner.player != null && Owner.player.cheats & CF_PREDICTING)) + { + return; + } + // [RH] The "blinking" can't check against EffectTics exactly or it will + // never happen, because InitEffect ensures that EffectTics will always + // be odd when level.time is even. + level.frozen = ( EffectTics > 4*32 + || (( EffectTics > 3*32 && EffectTics <= 4*32 ) && ((EffectTics + 1) & 15) != 0 ) + || (( EffectTics > 2*32 && EffectTics <= 3*32 ) && ((EffectTics + 1) & 7) != 0 ) + || (( EffectTics > 32 && EffectTics <= 2*32 ) && ((EffectTics + 1) & 3) != 0 ) + || (( EffectTics > 0 && EffectTics <= 1*32 ) && ((EffectTics + 1) & 1) != 0 )); + } + + //=========================================================================== + // + // APowerTimeFreezer :: EndEffect + // + //=========================================================================== + + override void EndEffect() + { + Super.EndEffect(); + + // If there is an owner, remove the timefreeze flag corresponding to + // her from all players. + if (Owner != null && Owner.player != null) + { + int freezemask = ~(1 << Owner.PlayerNumber()); + for (int i = 0; i < MAXPLAYERS; ++i) + { + players[i].timefreezer &= freezemask; + } + } + + // Are there any players who still have timefreezer bits set? + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].timefreezer != 0) + { + return; + } + } + + // No, so allow other actors to move about freely once again. + level.frozen = false; + + // Also, turn the music back on. + S_ResumeSound(false); + } } //===========================================================================