From 30a8541a1576bf4023b71deefba1cc09a4a4bc43 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Wed, 18 Jan 2017 17:26:12 +0100 Subject: [PATCH] - scriptified the weapon piece functions. - fixed: ClearInventory did not process depleted items properly. - changed HexenArmor from UNDROPPABLE to UNTOSSABLE because this allowed to remove some special handling in ClearInventory. The only other place which checks this flag also checks UNTOSSABLE. --- src/d_dehacked.cpp | 2 +- src/g_inventory/a_pickups.cpp | 74 +------ src/g_inventory/a_weaponpiece.cpp | 181 +---------------- src/g_inventory/a_weaponpiece.h | 5 - src/g_shared/sbarinfo_commands.cpp | 2 + src/p_mobj.cpp | 7 +- wadsrc/static/zscript.txt | 1 + wadsrc/static/zscript/inventory/armor.txt | 2 +- wadsrc/static/zscript/inventory/inventory.txt | 120 +++++++---- .../static/zscript/inventory/weaponpiece.txt | 186 ++++++++++++++++++ wadsrc/static/zscript/inventory/weapons.txt | 21 -- wadsrc/static/zscript/shared/player_cheat.txt | 2 +- 12 files changed, 290 insertions(+), 313 deletions(-) create mode 100644 wadsrc/static/zscript/inventory/weaponpiece.txt diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index a300766429..7bda9b994d 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -3183,7 +3183,7 @@ bool ADehackedPickup::ShouldRespawn () void ADehackedPickup::PlayPickupSound (AActor *toucher) { if (RealPickup != nullptr) - RealPickup->PlayPickupSound (toucher); + RealPickup->CallPlayPickupSound (toucher); } void ADehackedPickup::DoPickupSpecial (AActor *toucher) diff --git a/src/g_inventory/a_pickups.cpp b/src/g_inventory/a_pickups.cpp index d5fa58a0bb..93500adc74 100644 --- a/src/g_inventory/a_pickups.cpp +++ b/src/g_inventory/a_pickups.cpp @@ -79,71 +79,6 @@ void PClassInventory::Finalize(FStateDefinitions &statedef) ((AActor*)Defaults)->flags |= MF_SPECIAL; } -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing1 -// -// Make a special thing visible again. -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing1) -{ - PARAM_SELF_PROLOGUE(AInventory); - - self->renderflags &= ~RF_INVISIBLE; - if (self->DoRespawn ()) - { - S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE); - } - return 0; -} - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialThing2 -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialThing2) -{ - PARAM_SELF_PROLOGUE(AInventory); - - self->flags |= MF_SPECIAL; - if (!(self->GetDefault()->flags & MF_NOGRAVITY)) - { - self->flags &= ~MF_NOGRAVITY; - } - self->SetState (self->SpawnState); - return 0; -} - - -//--------------------------------------------------------------------------- -// -// PROC A_RestoreSpecialDoomThing -// -//--------------------------------------------------------------------------- - -DEFINE_ACTION_FUNCTION(AInventory, A_RestoreSpecialDoomThing) -{ - PARAM_SELF_PROLOGUE(AInventory); - - self->renderflags &= ~RF_INVISIBLE; - self->flags |= MF_SPECIAL; - if (!(self->GetDefault()->flags & MF_NOGRAVITY)) - { - self->flags &= ~MF_NOGRAVITY; - } - if (self->DoRespawn ()) - { - self->SetState (self->SpawnState); - S_Sound (self, CHAN_VOICE, "misc/spawn", 1, ATTN_IDLE); - Spawn ("ItemFog", self->Pos(), ALLOW_REPLACE); - } - return 0; -} - int AInventory::StaticLastMessageTic; FString AInventory::StaticLastMessage; @@ -907,7 +842,7 @@ void AInventory::Touch (AActor *toucher) // real player to make noise. if (player != NULL) { - PlayPickupSound (player->mo); + CallPlayPickupSound (player->mo); if (!(ItemFlags & IF_NOSCREENFLASH)) { player->bonuscount = BONUSADD; @@ -915,7 +850,7 @@ void AInventory::Touch (AActor *toucher) } else { - PlayPickupSound (toucher); + CallPlayPickupSound (toucher); } } @@ -1272,6 +1207,11 @@ bool AInventory::DoRespawn () return true; } +DEFINE_ACTION_FUNCTION(AInventory, DoRespawn) +{ + PARAM_SELF_PROLOGUE(AInventory); + ACTION_RETURN_BOOL(self->DoRespawn()); +} //=========================================================================== // diff --git a/src/g_inventory/a_weaponpiece.cpp b/src/g_inventory/a_weaponpiece.cpp index 2fe14ae91d..765547d4d1 100644 --- a/src/g_inventory/a_weaponpiece.cpp +++ b/src/g_inventory/a_weaponpiece.cpp @@ -78,181 +78,6 @@ void AWeaponPiece::Serialize(FSerializer &arc) ("piecevalue", PieceValue, def->PieceValue); } -//========================================================================== -// -// TryPickupWeaponPiece -// -//========================================================================== - -bool AWeaponPiece::TryPickupRestricted (AActor *&toucher) -{ - // Wrong class, but try to pick up for ammo - if (CallShouldStay()) - { // Can't pick up weapons for other classes in coop netplay - return false; - } - - AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); - - bool gaveSome = !!(toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + - toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2)); - - if (gaveSome) - { - GoAwayAndDie (); - } - return gaveSome; -} - - -//========================================================================== -// -// TryPickupWeaponPiece -// -//========================================================================== - -bool AWeaponPiece::TryPickup (AActor *&toucher) -{ - AInventory * inv; - AWeaponHolder * hold=NULL; - bool shouldStay = PrivateShouldStay (); - int gaveAmmo; - AWeapon * Defaults=(AWeapon*)GetDefaultByType(WeaponClass); - - FullWeapon=NULL; - for(inv=toucher->Inventory;inv;inv=inv->Inventory) - { - if (inv->IsKindOf(RUNTIME_CLASS(AWeaponHolder))) - { - hold=static_cast(inv); - - if (hold->PieceWeapon==WeaponClass) break; - hold=NULL; - } - } - if (!hold) - { - hold=static_cast(Spawn(RUNTIME_CLASS(AWeaponHolder))); - hold->BecomeItem(); - hold->AttachToOwner(toucher); - hold->PieceMask=0; - hold->PieceWeapon=WeaponClass; - } - - - if (shouldStay) - { - // Cooperative net-game - if (hold->PieceMask & PieceValue) - { - // Already has the piece - return false; - } - toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1); - toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); - } - else - { // Deathmatch or singleplayer game - gaveAmmo = toucher->GiveAmmo (Defaults->AmmoType1, Defaults->AmmoGive1) + - toucher->GiveAmmo (Defaults->AmmoType2, Defaults->AmmoGive2); - - if (hold->PieceMask & PieceValue) - { - // Already has the piece, check if mana needed - if (!gaveAmmo) return false; - GoAwayAndDie(); - return true; - } - } - - hold->PieceMask |= PieceValue; - - // Check if weapon assembled - if (hold->PieceMask== (1<health)-1) - { - if (!toucher->FindInventory (WeaponClass)) - { - FullWeapon= static_cast(Spawn(WeaponClass)); - - // The weapon itself should not give more ammo to the player! - FullWeapon->AmmoGive1=0; - FullWeapon->AmmoGive2=0; - FullWeapon->AttachToOwner(toucher); - FullWeapon->AmmoGive1=Defaults->AmmoGive1; - FullWeapon->AmmoGive2=Defaults->AmmoGive2; - } - } - GoAwayAndDie(); - return true; -} - -//=========================================================================== -// -// -// -//=========================================================================== - -bool AWeaponPiece::ShouldStay () -{ - return PrivateShouldStay (); -} - -//=========================================================================== -// -// -// -//=========================================================================== - -bool AWeaponPiece::PrivateShouldStay () -{ - // We want a weapon piece to behave like a weapon, so follow the exact - // same logic as weapons when deciding whether or not to stay. - if (((multiplayer && - (!deathmatch && !alwaysapplydmflags)) || (dmflags & DF_WEAPONS_STAY)) && - !(flags&MF_DROPPED)) - { - return true; - } - return false; -} - -//=========================================================================== -// -// PickupMessage -// -// Returns the message to print when this actor is picked up. -// -//=========================================================================== - -FString AWeaponPiece::PickupMessage () -{ - if (FullWeapon) - { - return FullWeapon->PickupMessage(); - } - else - { - return Super::PickupMessage(); - } -} - -//=========================================================================== -// -// DoPlayPickupSound -// -// Plays a sound when this actor is picked up. -// -//=========================================================================== - -void AWeaponPiece::PlayPickupSound (AActor *toucher) -{ - if (FullWeapon) - { - FullWeapon->PlayPickupSound(toucher); - } - else - { - Super::PlayPickupSound(toucher); - } -} - +DEFINE_FIELD(AWeaponPiece, PieceValue); +DEFINE_FIELD(AWeaponPiece, WeaponClass); +DEFINE_FIELD(AWeaponPiece, FullWeapon); diff --git a/src/g_inventory/a_weaponpiece.h b/src/g_inventory/a_weaponpiece.h index ca5ed6a06e..de5d935363 100644 --- a/src/g_inventory/a_weaponpiece.h +++ b/src/g_inventory/a_weaponpiece.h @@ -11,11 +11,6 @@ protected: public: virtual void Serialize(FSerializer &arc) override; - virtual bool TryPickup (AActor *&toucher) override; - virtual bool TryPickupRestricted (AActor *&toucher) override; - virtual bool ShouldStay () override; - virtual FString PickupMessage () override; - virtual void PlayPickupSound (AActor *toucher) override; int PieceValue; PClassActor *WeaponClass; diff --git a/src/g_shared/sbarinfo_commands.cpp b/src/g_shared/sbarinfo_commands.cpp index 5e15148817..85506edc54 100644 --- a/src/g_shared/sbarinfo_commands.cpp +++ b/src/g_shared/sbarinfo_commands.cpp @@ -3691,3 +3691,5 @@ SBarInfoCommand *SBarInfoCommandFlowControl::NextCommand(FScanner &sc) sc.MustGetToken('}'); return NULL; } + + diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 045679b830..78873a322d 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1211,12 +1211,7 @@ void AActor::ClearInventory() if (!(inv->ItemFlags & IF_UNDROPPABLE)) { inv->DepleteOrDestroy(); - } - else if (inv->GetClass() == RUNTIME_CLASS(AHexenArmor)) - { - AHexenArmor *harmor = static_cast (inv); - harmor->Slots[3] = harmor->Slots[2] = harmor->Slots[1] = harmor->Slots[0] = 0; - invp = &inv->Inventory; + if (!(inv->ObjectFlags & OF_EuthanizeMe)) invp = &inv->Inventory; // was only depleted so advance the pointer manually. } else { diff --git a/wadsrc/static/zscript.txt b/wadsrc/static/zscript.txt index fd8bce922a..6f0e3a5162 100644 --- a/wadsrc/static/zscript.txt +++ b/wadsrc/static/zscript.txt @@ -9,6 +9,7 @@ #include "zscript/inventory/inventory.txt" #include "zscript/inventory/inv_misc.txt" #include "zscript/inventory/weapons.txt" +#include "zscript/inventory/weaponpiece.txt" #include "zscript/inventory/armor.txt" #include "zscript/inventory/ammo.txt" #include "zscript/inventory/health.txt" diff --git a/wadsrc/static/zscript/inventory/armor.txt b/wadsrc/static/zscript/inventory/armor.txt index 3e7f57e21c..73ad73d1b8 100644 --- a/wadsrc/static/zscript/inventory/armor.txt +++ b/wadsrc/static/zscript/inventory/armor.txt @@ -66,7 +66,7 @@ class HexenArmor : Armor native Default { +Inventory.KEEPDEPLETED - +Inventory.UNDROPPABLE + +Inventory.UNTOSSABLE } } diff --git a/wadsrc/static/zscript/inventory/inventory.txt b/wadsrc/static/zscript/inventory/inventory.txt index 3e01d059ed..fbd4ed0886 100644 --- a/wadsrc/static/zscript/inventory/inventory.txt +++ b/wadsrc/static/zscript/inventory/inventory.txt @@ -47,44 +47,12 @@ class Inventory : Actor native virtual native bool DrawPowerup(int x, int y); virtual native void AbsorbDamage (int damage, Name damageType, out int newdamage); - //=========================================================================== - // - // AInventory :: Travelled - // - // Called when an item in somebody's inventory is carried over to another - // map, in case it needs to do special reinitialization. - // - //=========================================================================== - - virtual void Travelled() {} - - //=========================================================================== - // - // AInventory :: DoEffect - // - // Handles any effect an item might apply to its owner - // Normally only used by subclasses of Powerup - // - //=========================================================================== - - virtual void DoEffect() {} - - virtual double GetSpeedFactor() { return 1; } - virtual bool GetNoTeleportFreeze() { return false; } - virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} - virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {} - virtual void OwnerDied() {} - + native bool DoRespawn(); native bool GoAway(); native void GoAwayAndDie(); native void BecomeItem(); native void BecomePickup(); - // These are regular functions for the item itself. - private native void A_RestoreSpecialDoomThing(); - private native void A_RestoreSpecialThing1(); - private native void A_RestoreSpecialThing2(); - // In this case the caller function is more than a simple wrapper around the virtual method and // is what must be actually called to pick up an item. virtual protected native bool TryPickup(in out Actor toucher); @@ -112,6 +80,92 @@ class Inventory : Actor native TNT1 A 1; Stop; } + + // These are regular functions for the item itself. + + //--------------------------------------------------------------------------- + // + // PROC A_RestoreSpecialThing1 + // + // Make a special thing visible again. + // + //--------------------------------------------------------------------------- + + void A_RestoreSpecialThing1() + { + bInvisible = false; + if (DoRespawn ()) + { + A_PlaySound ("misc/spawn", CHAN_VOICE); + } + } + + //--------------------------------------------------------------------------- + // + // PROC A_RestoreSpecialThing2 + // + //--------------------------------------------------------------------------- + + void A_RestoreSpecialThing2() + { + bSpecial = true; + if (!Default.bNoGravity) + { + bNoGravity = false; + } + SetState (SpawnState); + } + + //--------------------------------------------------------------------------- + // + // PROC A_RestoreSpecialDoomThing + // + //--------------------------------------------------------------------------- + + void A_RestoreSpecialDoomThing() + { + bInvisible = false; + bSpecial = true; + if (!Default.bNoGravity) + { + bNoGravity = false; + } + if (DoRespawn ()) + { + SetState (SpawnState); + A_PlaySound ("misc/spawn", CHAN_VOICE); + Spawn ("ItemFog", Pos, ALLOW_REPLACE); + } + } + + //=========================================================================== + // + // AInventory :: Travelled + // + // Called when an item in somebody's inventory is carried over to another + // map, in case it needs to do special reinitialization. + // + //=========================================================================== + + virtual void Travelled() {} + + //=========================================================================== + // + // AInventory :: DoEffect + // + // Handles any effect an item might apply to its owner + // Normally only used by subclasses of Powerup + // + //=========================================================================== + + virtual void DoEffect() {} + + virtual double GetSpeedFactor() { return 1; } + virtual bool GetNoTeleportFreeze() { return false; } + virtual void ModifyDamage(int damage, Name damageType, out int newdamage, bool passive) {} + virtual void AlterWeaponSprite(VisStyle vis, in out int changed) {} + virtual void OwnerDied() {} + } class StateProvider : Inventory native diff --git a/wadsrc/static/zscript/inventory/weaponpiece.txt b/wadsrc/static/zscript/inventory/weaponpiece.txt new file mode 100644 index 0000000000..bd729f4e88 --- /dev/null +++ b/wadsrc/static/zscript/inventory/weaponpiece.txt @@ -0,0 +1,186 @@ +class WeaponHolder : Inventory native +{ + native int PieceMask; + native Class PieceWeapon; + + Default + { + +NOBLOCKMAP + +NOSECTOR + +INVENTORY.UNDROPPABLE + } +} + +class WeaponPiece : Inventory native +{ + Default + { + +WEAPONSPAWN; + } + + native int PieceValue; + native Class WeaponClass; + native Weapon FullWeapon; + + //========================================================================== + // + // TryPickupWeaponPiece + // + //========================================================================== + + override bool TryPickupRestricted (in out Actor toucher) + { + // Wrong class, but try to pick up for ammo + if (ShouldStay()) + { // Can't pick up weapons for other classes in coop netplay + return false; + } + + let Defaults = GetDefaultByType(WeaponClass); + + bool gaveSome = !!(toucher.GiveAmmo (Defaults.AmmoType1, Defaults.AmmoGive1) + + toucher.GiveAmmo (Defaults.AmmoType2, Defaults.AmmoGive2)); + + if (gaveSome) + { + GoAwayAndDie (); + } + return gaveSome; + } + + //========================================================================== + // + // TryPickupWeaponPiece + // + //========================================================================== + + override bool TryPickup (in out Actor toucher) + { + Inventory item; + WeaponHolder hold = NULL; + bool shouldStay = ShouldStay (); + int gaveAmmo; + let Defaults = GetDefaultByType(WeaponClass); + + FullWeapon = NULL; + for(item=toucher.Inv; item; item=item.Inv) + { + hold = WeaponHolder(item); + if (hold != null) + { + if (hold.PieceWeapon == WeaponClass) + { + break; + } + hold = NULL; + } + } + if (!hold) + { + hold = WeaponHolder(Spawn("WeaponHolder")); + hold.BecomeItem(); + hold.AttachToOwner(toucher); + hold.PieceMask = 0; + hold.PieceWeapon = WeaponClass; + } + + if (shouldStay) + { + // Cooperative net-game + if (hold.PieceMask & PieceValue) + { + // Already has the piece + return false; + } + toucher.GiveAmmo (Defaults.AmmoType1, Defaults.AmmoGive1); + toucher.GiveAmmo (Defaults.AmmoType2, Defaults.AmmoGive2); + } + else + { // Deathmatch or singleplayer game + gaveAmmo = toucher.GiveAmmo (Defaults.AmmoType1, Defaults.AmmoGive1) + + toucher.GiveAmmo (Defaults.AmmoType2, Defaults.AmmoGive2); + + if (hold.PieceMask & PieceValue) + { + // Already has the piece, check if mana needed + if (!gaveAmmo) return false; + GoAwayAndDie(); + return true; + } + } + + hold.PieceMask |= PieceValue; + + // Check if weapon assembled + if (hold.PieceMask == (1 << Defaults.health) - 1) + { + if (!toucher.FindInventory (WeaponClass)) + { + FullWeapon= Weapon(Spawn(WeaponClass)); + + // The weapon itself should not give more ammo to the player. + FullWeapon.AmmoGive1 = 0; + FullWeapon.AmmoGive2 = 0; + FullWeapon.AttachToOwner(toucher); + FullWeapon.AmmoGive1 = Defaults.AmmoGive1; + FullWeapon.AmmoGive2 = Defaults.AmmoGive2; + } + } + GoAwayAndDie(); + return true; + } + + //=========================================================================== + // + // + // + //=========================================================================== + + override bool ShouldStay () + { + // We want a weapon piece to behave like a weapon, so follow the exact + // same logic as weapons when deciding whether or not to stay. + return (((multiplayer && + (!deathmatch && !alwaysapplydmflags)) || sv_weaponstay) && !bDropped); + } + + //=========================================================================== + // + // PickupMessage + // + // Returns the message to print when this actor is picked up. + // + //=========================================================================== + + override String PickupMessage () + { + if (FullWeapon) + { + return FullWeapon.PickupMessage(); + } + else + { + return Super.PickupMessage(); + } + } + + //=========================================================================== + // + // DoPlayPickupSound + // + // Plays a sound when this actor is picked up. + // + //=========================================================================== + + override void PlayPickupSound (Actor toucher) + { + if (FullWeapon) + { + FullWeapon.PlayPickupSound(toucher); + } + else + { + Super.PlayPickupSound(toucher); + } + } +} diff --git a/wadsrc/static/zscript/inventory/weapons.txt b/wadsrc/static/zscript/inventory/weapons.txt index ba2bf2ef55..303dc6aa96 100644 --- a/wadsrc/static/zscript/inventory/weapons.txt +++ b/wadsrc/static/zscript/inventory/weapons.txt @@ -104,27 +104,6 @@ class WeaponGiver : Weapon native } } -class WeaponHolder : Inventory native -{ - native int PieceMask; - native Class PieceWeapon; - - Default - { - +NOBLOCKMAP - +NOSECTOR - +INVENTORY.UNDROPPABLE - } -} - -class WeaponPiece : Inventory native -{ - Default - { - +WEAPONSPAWN; - } -} - struct WeaponSlots native { native bool, int, int LocateWeapon(class weap); diff --git a/wadsrc/static/zscript/shared/player_cheat.txt b/wadsrc/static/zscript/shared/player_cheat.txt index 01b0595409..b88c387a14 100644 --- a/wadsrc/static/zscript/shared/player_cheat.txt +++ b/wadsrc/static/zscript/shared/player_cheat.txt @@ -399,4 +399,4 @@ extend class PlayerPawn } return; } -} \ No newline at end of file +}