diff --git a/src/am_map.cpp b/src/am_map.cpp index 8fb46ed6b..8c250ee68 100644 --- a/src/am_map.cpp +++ b/src/am_map.cpp @@ -3050,7 +3050,7 @@ void AM_Drawer () return; bool allmap = (level.flags2 & LEVEL2_ALLMAP) != 0; - bool allthings = allmap && players[consoleplayer].mo->FindInventory(RUNTIME_CLASS(APowerScanner), true) != NULL; + bool allthings = allmap && players[consoleplayer].mo->FindInventory(PClass::FindActor(NAME_PowerScanner), true) != nullptr; if (am_portaloverlay) { diff --git a/src/g_inventory/a_artifacts.cpp b/src/g_inventory/a_artifacts.cpp index 35bfa6e78..856aa5bb5 100644 --- a/src/g_inventory/a_artifacts.cpp +++ b/src/g_inventory/a_artifacts.cpp @@ -21,6 +21,7 @@ #include "v_palette.h" #include "serializer.h" #include "r_utility.h" +#include "virtual.h" #include "r_data/colormaps.h" @@ -182,6 +183,25 @@ void APowerup::InitEffect () { } +DEFINE_ACTION_FUNCTION(APowerup, InitEffect) +{ + PARAM_SELF_PROLOGUE(APowerup); + self->InitEffect(); + return 0; +} + +void APowerup::CallInitEffect() +{ + IFVIRTUAL(APowerup, InitEffect) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } + else InitEffect(); +} + + //=========================================================================== // // APowerup :: DoEffect @@ -230,6 +250,25 @@ void APowerup::EndEffect () } } +DEFINE_ACTION_FUNCTION(APowerup, EndEffect) +{ + PARAM_SELF_PROLOGUE(APowerup); + self->EndEffect(); + return 0; +} + +void APowerup::CallEndEffect() +{ + IFVIRTUAL(APowerup, EndEffect) + { + VMValue params[1] = { (DObject*)this }; + VMFrameStack stack; + GlobalVMStack.Call(func, params, 1, nullptr, 0, nullptr); + } + else EndEffect(); +} + + //=========================================================================== // // APowerup :: Destroy @@ -238,7 +277,7 @@ void APowerup::EndEffect () void APowerup::Destroy () { - EndEffect (); + CallEndEffect (); Super::Destroy (); } @@ -325,7 +364,7 @@ AInventory *APowerup::CreateCopy (AActor *other) // properly attached to anything yet. Owner = other; // Actually activate the powerup. - InitEffect (); + CallInitEffect (); // Clear the Owner field, unless it was // changed by the activation, for example, // if this instance is a morph powerup; @@ -599,7 +638,7 @@ void APowerInvisibility::InitEffect () flags5 &= ~(Owner->flags5 & INVISIBILITY_FLAGS5); Owner->flags5 |= flags5 & INVISIBILITY_FLAGS5; - DoEffect(); + CallDoEffect(); } } @@ -1262,7 +1301,7 @@ IMPLEMENT_CLASS(APowerTargeter, false, false) void APowerTargeter::Travelled () { - InitEffect (); + CallInitEffect (); } void APowerTargeter::InitEffect () @@ -1300,14 +1339,14 @@ void APowerTargeter::AttachToOwner(AActor *other) Super::AttachToOwner(other); // Let's actually properly call this for the targeters. - InitEffect(); + CallInitEffect(); } bool APowerTargeter::HandlePickup(AInventory *item) { if (Super::HandlePickup(item)) { - InitEffect(); // reset the HUD sprites + CallInitEffect(); // reset the HUD sprites return true; } return false; @@ -1443,10 +1482,6 @@ void APowerBuddha::EndEffect () Owner->player->cheats &= ~CF_BUDDHA; } -// Scanner powerup ---------------------------------------------------------- - -IMPLEMENT_CLASS(APowerScanner, false, false) - // Time freezer powerup ----------------------------------------------------- IMPLEMENT_CLASS( APowerTimeFreezer, false, false) @@ -1709,144 +1744,6 @@ void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage } } -// Drain rune ------------------------------------------------------- - -IMPLEMENT_CLASS(APowerDrain, false, false) - -//=========================================================================== -// -// ARuneDrain :: InitEffect -// -//=========================================================================== - -void APowerDrain::InitEffect( ) -{ - Super::InitEffect(); - - if (Owner== NULL || Owner->player == NULL) - return; - - // Give the player the power to drain life from opponents when he damages them. - Owner->player->cheats |= CF_DRAIN; -} - -//=========================================================================== -// -// ARuneDrain :: EndEffect -// -//=========================================================================== - -void APowerDrain::EndEffect( ) -{ - Super::EndEffect(); - - // Nothing to do if there's no owner. - if (Owner != NULL && Owner->player != NULL) - { - // Take away the drain power. - Owner->player->cheats &= ~CF_DRAIN; - } -} - - -// Regeneration rune ------------------------------------------------------- - -IMPLEMENT_CLASS(APowerRegeneration, false, false) - -//=========================================================================== -// -// APowerRegeneration :: DoEffect -// -//=========================================================================== - -void APowerRegeneration::DoEffect() -{ - Super::DoEffect(); - if (Owner != NULL && Owner->health > 0 && (level.time & 31) == 0) - { - if (P_GiveBody(Owner, int(Strength))) - { - S_Sound(Owner, CHAN_ITEM, "*regenerate", 1, ATTN_NORM ); - } - } -} - -// High jump rune ------------------------------------------------------- - -IMPLEMENT_CLASS(APowerHighJump, false, false) - -//=========================================================================== -// -// ARuneHighJump :: InitEffect -// -//=========================================================================== - -void APowerHighJump::InitEffect( ) -{ - Super::InitEffect(); - - if (Owner== NULL || Owner->player == NULL) - return; - - // Give the player the power to jump much higher. - Owner->player->cheats |= CF_HIGHJUMP; -} - -//=========================================================================== -// -// ARuneHighJump :: EndEffect -// -//=========================================================================== - -void APowerHighJump::EndEffect( ) -{ - Super::EndEffect(); - // Nothing to do if there's no owner. - if (Owner != NULL && Owner->player != NULL) - { - // Take away the high jump power. - Owner->player->cheats &= ~CF_HIGHJUMP; - } -} - -// Double firing speed rune --------------------------------------------- - -IMPLEMENT_CLASS(APowerDoubleFiringSpeed, false, false) - -//=========================================================================== -// -// APowerDoubleFiringSpeed :: InitEffect -// -//=========================================================================== - -void APowerDoubleFiringSpeed::InitEffect( ) -{ - Super::InitEffect(); - - if (Owner== NULL || Owner->player == NULL) - return; - - // Give the player the power to shoot twice as fast. - Owner->player->cheats |= CF_DOUBLEFIRINGSPEED; -} - -//=========================================================================== -// -// APowerDoubleFiringSpeed :: EndEffect -// -//=========================================================================== - -void APowerDoubleFiringSpeed::EndEffect( ) -{ - Super::EndEffect(); - // Nothing to do if there's no owner. - if (Owner != NULL && Owner->player != NULL) - { - // Take away the shooting twice as fast power. - Owner->player->cheats &= ~CF_DOUBLEFIRINGSPEED; - } -} - // Morph powerup ------------------------------------------------------ IMPLEMENT_CLASS(APowerMorph, false, true) @@ -1955,42 +1852,3 @@ void APowerMorph::EndEffect( ) MorphedPlayer = NULL; } -// Infinite Ammo Powerup ----------------------------------------------------- - -IMPLEMENT_CLASS(APowerInfiniteAmmo, false, false) - -//=========================================================================== -// -// APowerInfiniteAmmo :: InitEffect -// -//=========================================================================== - -void APowerInfiniteAmmo::InitEffect( ) -{ - Super::InitEffect(); - - if (Owner== NULL || Owner->player == NULL) - return; - - // Give the player infinite ammo - Owner->player->cheats |= CF_INFINITEAMMO; -} - -//=========================================================================== -// -// APowerInfiniteAmmo :: EndEffect -// -//=========================================================================== - -void APowerInfiniteAmmo::EndEffect( ) -{ - Super::EndEffect(); - - // Nothing to do if there's no owner. - if (Owner != NULL && Owner->player != NULL) - { - // Take away the limitless ammo - Owner->player->cheats &= ~CF_INFINITEAMMO; - } -} - diff --git a/src/g_inventory/a_artifacts.h b/src/g_inventory/a_artifacts.h index bb821b5d6..f68516de7 100644 --- a/src/g_inventory/a_artifacts.h +++ b/src/g_inventory/a_artifacts.h @@ -26,11 +26,15 @@ public: FNameNoInit Mode; double Strength; -protected: +public: virtual void InitEffect (); virtual void DoEffect () override; virtual void EndEffect (); +protected: + void CallInitEffect(); + void CallEndEffect(); + friend void EndAllPowerupEffects(AInventory *item); friend void InitAllPowerupEffects(AInventory *item); }; @@ -161,11 +165,6 @@ class APowerMinotaur : public APowerup DECLARE_CLASS (APowerMinotaur, APowerup) }; -class APowerScanner : public APowerup -{ - DECLARE_CLASS (APowerScanner, APowerup) -}; - class APowerTargeter : public APowerup { DECLARE_CLASS (APowerTargeter, APowerup) @@ -222,45 +221,6 @@ protected: virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) override; }; -class APowerDrain : public APowerup -{ - DECLARE_CLASS( APowerDrain, APowerup ) -protected: - virtual void InitEffect() override; - virtual void EndEffect() override; -}; - -class APowerRegeneration : public APowerup -{ - DECLARE_CLASS( APowerRegeneration, APowerup ) -protected: - virtual void DoEffect() override; -}; - -class APowerHighJump : public APowerup -{ - DECLARE_CLASS( APowerHighJump, APowerup ) -protected: - virtual void InitEffect() override; - virtual void EndEffect() override; -}; - -class APowerDoubleFiringSpeed : public APowerup -{ - DECLARE_CLASS( APowerDoubleFiringSpeed, APowerup ) -protected: - virtual void InitEffect() override; - virtual void EndEffect() override; -}; - -class APowerInfiniteAmmo : public APowerup -{ - DECLARE_CLASS( APowerInfiniteAmmo, APowerup ) -protected: - virtual void InitEffect() override; - virtual void EndEffect() override; -}; - class APowerMorph : public APowerup { DECLARE_CLASS( APowerMorph, APowerup ) diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 136c096a3..7550ff0da 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -585,7 +585,7 @@ void EndAllPowerupEffects(AInventory *item) { if (item->IsKindOf(RUNTIME_CLASS(APowerup))) { - static_cast(item)->EndEffect(); + static_cast(item)->CallEndEffect(); } item = item->Inventory; } @@ -605,7 +605,7 @@ void InitAllPowerupEffects(AInventory *item) { if (item->IsKindOf(RUNTIME_CLASS(APowerup))) { - static_cast(item)->InitEffect(); + static_cast(item)->CallInitEffect(); } item = item->Inventory; } diff --git a/src/namedef.h b/src/namedef.h index d50f8131d..45e1e67f2 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -354,6 +354,7 @@ xx(MapSpot) xx(PatrolPoint) xx(PatrolSpecial) xx(Communicator) +xx(PowerScanner) // Textmap properties //xx(X) diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 102142d38..9aa178e64 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -1545,7 +1545,7 @@ dopain: target->SetState (target->SeeState); } } - else if ((damage > 0 || fakedPain) && source != target->target && target->OkayToSwitchTarget (source)) + else if (source != target->target && target->OkayToSwitchTarget (source)) { // Target actor is not intent on another actor, // so make him chase after source diff --git a/src/p_map.cpp b/src/p_map.cpp index 1f53181f1..434db69f1 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -1298,7 +1298,7 @@ bool PIT_CheckThing(FMultiBlockThingsIterator &it, FMultiBlockThingsIterator::Ch if ((tm.thing->Z() >= topz) || (tm.thing->Top() <= thing->Z())) return true; } - // If they are not allowed to overlap, the rest of this function still needs to be executed. + else return unblocking; // This may not really make sense, but Heretic depends on the broken implementation. } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7e5dbc88e..8d31035a2 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3801,7 +3801,7 @@ void AActor::Tick () // by the order in the inventory, not the order in the thinker table while (item != NULL && item->Owner == this) { - item->DoEffect(); + item->CallDoEffect(); item = item->Inventory; } diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 9b3e22252..15066c0fd 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1059,3 +1059,32 @@ enum EPuffFlags PF_HITTHINGBLEED = 8, PF_NORANDOMZ = 16 }; + +enum EPlayerCheats +{ + CF_NOCLIP = 1 << 0, // No clipping, walk through barriers. + CF_GODMODE = 1 << 1, // No damage, no health loss. + CF_NOVELOCITY = 1 << 2, // Not really a cheat, just a debug aid. + CF_NOTARGET = 1 << 3, // [RH] Monsters don't target + CF_FLY = 1 << 4, // [RH] Flying player + CF_CHASECAM = 1 << 5, // [RH] Put camera behind player + CF_FROZEN = 1 << 6, // [RH] Don't let the player move + CF_REVERTPLEASE = 1 << 7, // [RH] Stick camera in player's head if (s)he moves + CF_STEPLEFT = 1 << 9, // [RH] Play left footstep sound next time + CF_FRIGHTENING = 1 << 10, // [RH] Scare monsters away + CF_INSTANTWEAPSWITCH= 1 << 11, // [RH] Switch weapons instantly + CF_TOTALLYFROZEN = 1 << 12, // [RH] All players can do is press +use + CF_PREDICTING = 1 << 13, // [RH] Player movement is being predicted + CF_INTERPVIEW = 1 << 14, // [RH] view was changed outside of input, so interpolate one frame + CF_DRAIN = 1 << 16, // Player owns a drain powerup + CF_HIGHJUMP = 1 << 18, // more Skulltag flags. Implementation not guaranteed though. ;) + CF_REFLECTION = 1 << 19, + CF_PROSPERITY = 1 << 20, + CF_DOUBLEFIRINGSPEED= 1 << 21, // Player owns a double firing speed artifact + CF_EXTREMELYDEAD = 1 << 22, // [RH] Reliably let the status bar know about extreme deaths. + CF_INFINITEAMMO = 1 << 23, // Player owns an infinite ammo artifact + CF_BUDDHA2 = 1 << 24, // [MC] Absolute buddha. No voodoo can kill it either. + CF_GODMODE2 = 1 << 25, // [MC] Absolute godmode. No voodoo can kill it either. + CF_BUDDHA = 1 << 27, // [SP] Buddha mode - take damage, but don't die + CF_NOCLIP2 = 1 << 30, // [RH] More Quake-like noclip +}; diff --git a/wadsrc/static/zscript/shared/powerups.txt b/wadsrc/static/zscript/shared/powerups.txt index d28799ff2..868951166 100644 --- a/wadsrc/static/zscript/shared/powerups.txt +++ b/wadsrc/static/zscript/shared/powerups.txt @@ -25,6 +25,9 @@ class Powerup : Inventory native // Note, that while this is an inventory flag, it only has meaning on an active powerup. override bool GetNoTeleportFreeze() { return bNoTeleportFreeze; } + + native virtual void InitEffect(); + native virtual void EndEffect(); } @@ -210,7 +213,13 @@ class PowerBuddha : Powerup native } } -class PowerScanner : Powerup native +//=========================================================================== +// +// Scanner (this is active just by being present) +// +//=========================================================================== + +class PowerScanner : Powerup { Default { @@ -243,26 +252,177 @@ class PowerProtection : Powerup native } } -class PowerDrain : Powerup native +//=========================================================================== +// +// Drain +// +//=========================================================================== + +class PowerDrain : Powerup { Default { Powerup.Duration -60; } + + override void InitEffect() + { + Super.InitEffect(); + + if (Owner!= null && Owner.player != null) + { + // Give the player the power to drain life from opponents when he damages them. + Owner.player.cheats |= CF_DRAIN; + } + } + + override void EndEffect() + { + Super.EndEffect(); + + // Nothing to do if there's no owner. + if (Owner!= null && Owner.player != null) + { + // Take away the drain power. + Owner.player.cheats &= ~CF_DRAIN; + } + } + } -class PowerRegeneration : Powerup native +//=========================================================================== +// +// Regeneration +// +//=========================================================================== + +class PowerRegeneration : Powerup { Default { Powerup.Duration -120; Powerup.Strength 5; } + + override void DoEffect() + { + Super.DoEffect(); + if (Owner != null && Owner.health > 0 && (level.time & 31) == 0) + { + if (Owner.GiveBody(int(Strength))) + { + Owner.A_PlaySound("*regenerate", CHAN_ITEM); + } + } + } } -class PowerHighJump : Powerup native {} +//=========================================================================== +// +// HighJump +// +//=========================================================================== -class PowerDoubleFiringSpeed : Powerup native {} +class PowerHighJump : Powerup +{ + override void InitEffect() + { + Super.InitEffect(); + + if (Owner!= null && Owner.player != null) + { + // Give the player the power to jump much higher. + Owner.player.cheats |= CF_HIGHJUMP; + } + } + + override void EndEffect() + { + Super.EndEffect(); + + // Nothing to do if there's no owner. + if (Owner!= null && Owner.player != null) + { + // Take away the high jump power. + Owner.player.cheats &= ~CF_HIGHJUMP; + } + } +} + +//=========================================================================== +// +// DoubleFiringSpeed +// +//=========================================================================== + +class PowerDoubleFiringSpeed : Powerup +{ + override void InitEffect() + { + Super.InitEffect(); + + if (Owner!= null && Owner.player != null) + { + // Give the player the power to shoot twice as fast. + Owner.player.cheats |= CF_DOUBLEFIRINGSPEED; + } + } + + override void EndEffect() + { + Super.EndEffect(); + + // Nothing to do if there's no owner. + if (Owner!= null && Owner.player != null) + { + // Take away the shooting twice as fast power. + Owner.player.cheats &= ~CF_DOUBLEFIRINGSPEED; + } + } +} + +//=========================================================================== +// +// InfiniteAmmo +// +//=========================================================================== + +class PowerInfiniteAmmo : Powerup +{ + Default + { + Powerup.Duration -30; + } + + override void InitEffect() + { + Super.InitEffect(); + + if (Owner!= null && Owner.player != null) + { + // Give the player infinite ammo + Owner.player.cheats |= CF_INFINITEAMMO; + } + } + + override void EndEffect() + { + Super.EndEffect(); + + // Nothing to do if there's no owner. + if (Owner!= null && Owner.player != null) + { + // Take away the limitless ammo + Owner.player.cheats &= ~CF_INFINITEAMMO; + } + } +} + +//=========================================================================== +// +// PowerMorph +// +//=========================================================================== class PowerMorph : Powerup native { @@ -278,11 +438,3 @@ class PowerMorph : Powerup native } } -class PowerInfiniteAmmo : Powerup native -{ - Default - { - Powerup.Duration -30; - } -} -