From 3af9232fca01dbcd30abf0242cf67bf57c80a216 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Tue, 29 Nov 2016 12:17:05 +0100 Subject: [PATCH] - scriptified a_strifeitems.cpp and a_debris.cpp. - Changed the glass shards so that they do not have to override FloorBounceMissile. It was the only place where this was virtually overridden and provided little usefulness. - made 'out' variables work. - fixed virtual call handling for HandlePickup. --- src/CMakeLists.txt | 2 - src/actor.h | 7 +- src/d_player.h | 2 +- src/g_level.cpp | 1 - src/g_shared/a_debris.cpp | 27 -- src/g_shared/a_pickups.cpp | 25 +- src/g_shared/a_pickups.h | 4 +- src/g_shared/sbarinfo.cpp | 1 - src/g_strife/a_strifeglobal.h | 38 -- src/g_strife/a_strifeitems.cpp | 377 ------------------ src/g_strife/a_strifestuff.cpp | 2 - src/g_strife/strife_sbar.cpp | 1 - src/m_cheat.cpp | 1 - src/p_acs.cpp | 1 - src/p_conversation.cpp | 3 +- src/p_lnspec.cpp | 5 +- src/p_mobj.cpp | 27 +- src/p_user.cpp | 4 +- src/scripting/codegeneration/codegen.cpp | 39 +- src/scripting/thingdef_data.cpp | 7 + src/scripting/zscript/zcc_compile.cpp | 19 +- src/virtual.h | 7 +- wadsrc/static/zscript/actor.txt | 3 +- wadsrc/static/zscript/constants.txt | 22 + wadsrc/static/zscript/doom/scriptedmarine.txt | 2 +- wadsrc/static/zscript/shared/debris.txt | 12 +- wadsrc/static/zscript/shared/inventory.txt | 3 +- wadsrc/static/zscript/strife/acolyte.txt | 4 +- wadsrc/static/zscript/strife/strifeitems.txt | 256 +++++++++++- 29 files changed, 374 insertions(+), 528 deletions(-) delete mode 100644 src/g_shared/a_debris.cpp delete mode 100644 src/g_strife/a_strifeitems.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ca87affa..923d545e0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,7 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_strifeitems.cpp g_strife/a_strifeweapons.cpp g_shared/sbarinfo_commands.cpp xlat/xlat_parser.y @@ -1119,7 +1118,6 @@ set (PCH_SOURCES g_shared/a_artifacts.cpp g_shared/a_bridge.cpp g_shared/a_camera.cpp - g_shared/a_debris.cpp g_shared/a_decals.cpp g_shared/a_fastprojectile.cpp g_shared/a_flashfader.cpp diff --git a/src/actor.h b/src/actor.h index b627bac66..0b6c58c19 100644 --- a/src/actor.h +++ b/src/actor.h @@ -648,7 +648,7 @@ public: void PlayBounceSound(bool onfloor); // Called when an actor with MF_MISSILE and MF2_FLOORBOUNCE hits the floor - virtual bool FloorBounceMissile (secplane_t &plane); + bool FloorBounceMissile (secplane_t &plane); // Called when an actor is to be reflected by a disc of repulsion. // Returns true to continue normal blast processing. @@ -682,7 +682,7 @@ public: // Give an item to the actor and pick it up. // Returns true if the item pickup succeeded. - virtual bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false); + bool GiveInventory (PClassInventory *type, int amount, bool givecheat = false); // Removes the item from the inventory list. virtual void RemoveInventory (AInventory *item); @@ -693,8 +693,7 @@ public: virtual bool TakeInventory (PClassActor *itemclass, int amount, bool fromdecorate = false, bool notakeinfinite = false); // Uses an item and removes it from the inventory. - virtual bool DoUseInventory (AInventory *item); - bool UseInventory(AInventory *item); + virtual bool UseInventory (AInventory *item); // Tosses an item out of the inventory. AInventory *DropInventory (AInventory *item); diff --git a/src/d_player.h b/src/d_player.h index af06e9730..d1678b619 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -109,7 +109,7 @@ public: virtual void Tick(); virtual void AddInventory (AInventory *item); virtual void RemoveInventory (AInventory *item); - virtual bool DoUseInventory (AInventory *item); + virtual bool UseInventory (AInventory *item); virtual void MarkPrecacheSounds () const; virtual void PlayIdle (); diff --git a/src/g_level.cpp b/src/g_level.cpp index 0e7820d93..4bb78461a 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -79,7 +79,6 @@ #include "v_palette.h" #include "menu/menu.h" #include "a_sharedglobal.h" -#include "a_strifeglobal.h" #include "r_data/colormaps.h" #include "r_renderer.h" #include "r_utility.h" diff --git a/src/g_shared/a_debris.cpp b/src/g_shared/a_debris.cpp deleted file mode 100644 index 0932088c2..000000000 --- a/src/g_shared/a_debris.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "actor.h" -#include "info.h" -#include "m_random.h" -#include "m_fixed.h" - -// Stained glass ------------------------------------------------------------ - -class AGlassShard : public AActor -{ - DECLARE_CLASS (AGlassShard, AActor) -public: - bool FloorBounceMissile (secplane_t &plane) - { - if (!Super::FloorBounceMissile (plane)) - { - if (fabs (Vel.Z) < 0.5) - { - Destroy (); - } - return false; - } - return true; - } -}; - -IMPLEMENT_CLASS(AGlassShard, false, false) - diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index df434baae..38d068bd7 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -11,7 +11,6 @@ #include "c_dispatch.h" #include "gstrings.h" #include "templates.h" -#include "a_strifeglobal.h" #include "a_morph.h" #include "a_specialspot.h" #include "g_level.h" @@ -751,7 +750,7 @@ bool AInventory::CallHandlePickup(AInventory *item) auto self = this; while (self != nullptr) { - IFVIRTUAL(AInventory, HandlePickup) + IFVIRTUALPTR(self, AInventory, HandlePickup) { // Without the type cast this picks the 'void *' assignment... VMValue params[2] = { (DObject*)self, (DObject*)item }; @@ -1684,6 +1683,13 @@ bool AInventory::TryPickup (AActor *&toucher) return true; } +DEFINE_ACTION_FUNCTION(AInventory, TryPickup) +{ + PARAM_SELF_PROLOGUE(AInventory); + PARAM_POINTER(toucher, AActor*); + ACTION_RETURN_BOOL(self->TryPickup(*toucher)); +} + //=========================================================================== // // AInventory :: TryPickupRestricted @@ -1710,7 +1716,20 @@ bool AInventory::CallTryPickup (AActor *toucher, AActor **toucher_return) bool res; if (CanPickup(toucher)) - res = TryPickup(toucher); + { + bool res; + IFVIRTUAL(AInventory, TryPickup) + { + VMValue params[2] = { (DObject*)this, (void*)&toucher }; + VMReturn ret; + VMFrameStack stack; + int retval; + ret.IntAt(&retval); + stack.Call(func, params, 2, &ret, 1, nullptr); + res = !!retval; + } + else res = TryPickup(toucher); + } else if (!(ItemFlags & IF_RESTRICTABSOLUTELY)) res = TryPickupRestricted(toucher); // let an item decide for itself how it will handle this else diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 8fc96cd57..48afac226 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -222,9 +222,9 @@ public: virtual PalEntry GetBlend (); PalEntry CallGetBlend(); -protected: virtual bool TryPickup (AActor *&toucher); virtual bool TryPickupRestricted (AActor *&toucher); +protected: bool CanPickup(AActor * toucher); void GiveQuest(AActor * toucher); @@ -600,5 +600,7 @@ public: bool TryPickup(AActor *&toucher); }; +extern PClassActor *QuestItemClasses[31]; + #endif //__A_PICKUPS_H__ diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index ed91be4c7..4bb9d5b81 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -52,7 +52,6 @@ #include "r_data/r_translate.h" #include "a_artifacts.h" #include "a_weaponpiece.h" -#include "a_strifeglobal.h" #include "g_level.h" #include "v_palette.h" #include "p_acs.h" diff --git a/src/g_strife/a_strifeglobal.h b/src/g_strife/a_strifeglobal.h index adf8d59bf..9206dd08c 100644 --- a/src/g_strife/a_strifeglobal.h +++ b/src/g_strife/a_strifeglobal.h @@ -4,42 +4,4 @@ #include "info.h" #include "a_pickups.h" -// Base class for every humanoid in Strife that can go into -// a fire or electric death. -class ADegninOre : public AInventory -{ - DECLARE_CLASS (ADegninOre, AInventory) -public: - bool Use (bool pickup); -}; - -class ADummyStrifeItem : public AInventory -{ - DECLARE_CLASS (ADummyStrifeItem, AInventory) -}; - -class AUpgradeStamina : public ADummyStrifeItem -{ - DECLARE_CLASS (AUpgradeStamina, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -class AUpgradeAccuracy : public ADummyStrifeItem -{ - DECLARE_CLASS (AUpgradeAccuracy, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -class ASlideshowStarter : public ADummyStrifeItem -{ - DECLARE_CLASS (ASlideshowStarter, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - - -extern PClassActor *QuestItemClasses[31]; - #endif diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp deleted file mode 100644 index b9f3f288e..000000000 --- a/src/g_strife/a_strifeitems.cpp +++ /dev/null @@ -1,377 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "d_player.h" -#include "gstrings.h" -#include "p_local.h" -#include "p_spec.h" -#include "a_strifeglobal.h" -#include "p_lnspec.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "d_event.h" -#include "a_keys.h" -#include "c_console.h" -#include "templates.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ -// Degnin Ore --------------------------------------------------------------- - -IMPLEMENT_CLASS(ADegninOre, false, false) - -bool ADegninOre::Use (bool pickup) -{ - if (pickup) - { - return false; - } - else - { - AInventory *drop; - - // Increase the amount by one so that when DropInventory decrements it, - // the actor will have the same number of beacons that he started with. - // When we return to UseInventory, it will take care of decrementing - // Amount again and disposing of this item if there are no more. - Amount++; - drop = Owner->DropInventory (this); - if (drop == NULL) - { - Amount--; - return false; - } - return true; - } -} - -// Health Training ---------------------------------------------------------- - -class AHealthTraining : public AInventory -{ - DECLARE_CLASS (AHealthTraining, AInventory) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AHealthTraining, false, false) - -bool AHealthTraining::TryPickup (AActor *&toucher) -{ - if (Super::TryPickup (toucher)) - { - toucher->GiveInventoryType (PClass::FindActor("GunTraining")); - AInventory *coin = (AInventory*)Spawn("Coin"); - if (coin != NULL) - { - coin->Amount = toucher->player->mo->accuracy*5 + 300; - if (!coin->CallTryPickup (toucher)) - { - coin->Destroy (); - } - } - return true; - } - return false; -} - -// Scanner ------------------------------------------------------------------ - -class AScanner : public APowerupGiver -{ - DECLARE_CLASS (AScanner, APowerupGiver) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AScanner, false, false) - -bool AScanner::Use (bool pickup) -{ - if (!(level.flags2 & LEVEL2_ALLMAP)) - { - if (Owner->CheckLocalView (consoleplayer)) - { - C_MidPrint(SmallFont, GStrings("TXT_NEEDMAP")); - } - return false; - } - return Super::Use (pickup); -} - -// Prison Pass -------------------------------------------------------------- - -class APrisonPass : public AKey -{ - DECLARE_CLASS (APrisonPass, AKey) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(APrisonPass, false, false) - -bool APrisonPass::TryPickup (AActor *&toucher) -{ - Super::TryPickup (toucher); - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 223, 2., 0, 0, 0); - toucher->GiveInventoryType (QuestItemClasses[9]); - return true; -} - -//============================================================================ -// -// APrisonPass :: SpecialDropAction -// -// Trying to make a monster that drops a prison pass turns it into an -// OpenDoor223 item instead. That means the only way to get it in Strife -// is through dialog, which is why it doesn't have its own sprite. -// -//============================================================================ - -bool APrisonPass::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorOpen, NULL, dropper, 223, 2., 0, 0, 0); - Destroy (); - return true; -} - - -//--------------------------------------------------------------------------- -// Dummy items. They are just used by Strife to perform --------------------- -// actions and cannot be held. ---------------------------------------------- -//--------------------------------------------------------------------------- - -IMPLEMENT_CLASS(ADummyStrifeItem, false, false) - -// Sound the alarm! --------------------------------------------------------- - -class ARaiseAlarm : public ADummyStrifeItem -{ - DECLARE_CLASS (ARaiseAlarm, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(ARaiseAlarm, false, false) - -bool ARaiseAlarm::TryPickup (AActor *&toucher) -{ - P_NoiseAlert (toucher, toucher); - /* - ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); - Actor spectre = Actor(it.Next()); - - if (spectre != NULL && spectre.health > 0 && toucher != spectre) - { - spectre.CurSector.SoundTarget = spectre.LastHeard = toucher; - spectre.target = toucher; - spectre.SetState (spectre.SeeState); - } - - */ - GoAwayAndDie (); - return true; -} - -bool ARaiseAlarm::SpecialDropAction (AActor *dropper) -{ - if (dropper->target != nullptr) - { - P_NoiseAlert(dropper->target, dropper->target); - if (dropper->target->CheckLocalView(consoleplayer)) - { - Printf("You Fool! You've set off the alarm.\n"); - } - } - Destroy (); - return true; -} - -// Open door tag 222 -------------------------------------------------------- - -class AOpenDoor222 : public ADummyStrifeItem -{ - DECLARE_CLASS (AOpenDoor222, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AOpenDoor222, false, false) - -bool AOpenDoor222::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 222, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -// Close door tag 222 ------------------------------------------------------- - -class ACloseDoor222 : public ADummyStrifeItem -{ - DECLARE_CLASS (ACloseDoor222, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(ACloseDoor222, false, false) - -bool ACloseDoor222::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorClose, NULL, toucher, 222, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -bool ACloseDoor222::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorClose, NULL, dropper, 222, 2., 0, 0, 0); - if (dropper->target != nullptr) - { - if (dropper->target->CheckLocalView(consoleplayer)) - { - Printf("You're dead! You set off the alarm.\n"); - } - P_NoiseAlert(dropper->target, dropper->target); - } - Destroy (); - return true; -} - -// Open door tag 224 -------------------------------------------------------- - -class AOpenDoor224 : public ADummyStrifeItem -{ - DECLARE_CLASS (AOpenDoor224, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); - bool SpecialDropAction (AActor *dropper); -}; - -IMPLEMENT_CLASS(AOpenDoor224, false, false) - -bool AOpenDoor224::TryPickup (AActor *&toucher) -{ - EV_DoDoor (DDoor::doorOpen, NULL, toucher, 224, 2., 0, 0, 0); - GoAwayAndDie (); - return true; -} - -bool AOpenDoor224::SpecialDropAction (AActor *dropper) -{ - EV_DoDoor (DDoor::doorOpen, NULL, dropper, 224, 2., 0, 0, 0); - Destroy (); - return true; -} - -// Ammo --------------------------------------------------------------------- - -class AAmmoFillup : public ADummyStrifeItem -{ - DECLARE_CLASS (AAmmoFillup, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AAmmoFillup, false, false) - -bool AAmmoFillup::TryPickup (AActor *&toucher) -{ - PClassActor *clip = PClass::FindActor(NAME_ClipOfBullets); - if (clip != NULL) - { - AInventory *item = toucher->FindInventory(clip); - if (item == NULL) - { - item = toucher->GiveInventoryType (clip); - if (item != NULL) - { - item->Amount = 50; - } - } - else if (item->Amount < 50) - { - item->Amount = 50; - } - else - { - return false; - } - GoAwayAndDie (); - } - return true; -} - -// Health ------------------------------------------------------------------- - -class AHealthFillup : public ADummyStrifeItem -{ - DECLARE_CLASS (AHealthFillup, ADummyStrifeItem) -public: - bool TryPickup (AActor *&toucher); -}; - -IMPLEMENT_CLASS(AHealthFillup, false, false) - -bool AHealthFillup::TryPickup (AActor *&toucher) -{ - static const int skillhealths[5] = { -100, -75, -50, -50, -100 }; - - int index = clamp(gameskill, 0,4); - if (!P_GiveBody (toucher, skillhealths[index])) - { - return false; - } - GoAwayAndDie (); - return true; -} - -// Upgrade Stamina ---------------------------------------------------------- - -IMPLEMENT_CLASS(AUpgradeStamina, false, false) - -bool AUpgradeStamina::TryPickup (AActor *&toucher) -{ - if (toucher->player == NULL) - return false; - - toucher->player->mo->stamina += Amount; - if (toucher->player->mo->stamina >= MaxAmount) - toucher->player->mo->stamina = MaxAmount; - - P_GiveBody (toucher, -100); - GoAwayAndDie (); - return true; -} - -// Upgrade Accuracy --------------------------------------------------------- - -IMPLEMENT_CLASS(AUpgradeAccuracy, false, false) - -bool AUpgradeAccuracy::TryPickup (AActor *&toucher) -{ - if (toucher->player == NULL || toucher->player->mo->accuracy >= 100) - return false; - toucher->player->mo->accuracy += 10; - GoAwayAndDie (); - return true; -} - -// Start a slideshow -------------------------------------------------------- - -IMPLEMENT_CLASS(ASlideshowStarter, false, false) - -bool ASlideshowStarter::TryPickup (AActor *&toucher) -{ - gameaction = ga_slideshow; - if (level.levelnum == 10) - { - toucher->GiveInventoryType (QuestItemClasses[16]); - } - GoAwayAndDie (); - return true; -} diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index 6537f180e..e93c13600 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -6,7 +6,6 @@ #include "d_player.h" #include "a_action.h" #include "p_local.h" -#include "a_strifeglobal.h" #include "p_enemy.h" #include "p_lnspec.h" #include "c_console.h" @@ -24,7 +23,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_strifeitems.cpp" #include "a_strifeweapons.cpp" // Notes so I don't forget them: diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 79a363d1c..c12c7a723 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -12,7 +12,6 @@ #include "m_swap.h" #include "templates.h" #include "a_keys.h" -#include "a_strifeglobal.h" #include "gi.h" #include "g_level.h" #include "colormatcher.h" diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 33a90c85f..f5cd56848 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -30,7 +30,6 @@ #include "doomstat.h" #include "gstrings.h" #include "p_local.h" -#include "a_strifeglobal.h" #include "gi.h" #include "p_enemy.h" #include "sbar.h" diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 97f660246..a71110674 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -58,7 +58,6 @@ #include "sbar.h" #include "m_swap.h" #include "a_sharedglobal.h" -#include "a_strifeglobal.h" #include "v_video.h" #include "w_wad.h" #include "r_sky.h" diff --git a/src/p_conversation.cpp b/src/p_conversation.cpp index bf1c392ae..5fd21e73b 100644 --- a/src/p_conversation.cpp +++ b/src/p_conversation.cpp @@ -44,7 +44,6 @@ #include "m_random.h" #include "gi.h" #include "templates.h" -#include "a_strifeglobal.h" #include "a_keys.h" #include "p_enemy.h" #include "gstrings.h" @@ -1357,7 +1356,7 @@ static void HandleReply(player_t *player, bool isconsole, int nodenum, int reply } } - if (reply->GiveType->IsDescendantOf(RUNTIME_CLASS(ASlideshowStarter))) + if (reply->GiveType->IsDescendantOf(PClass::FindActor("SlideshowStarter"))) gameaction = ga_slideshow; } else diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 1f318f559..179e057b3 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -50,7 +50,6 @@ #include "gi.h" #include "m_random.h" #include "p_conversation.h" -#include "a_strifeglobal.h" #include "r_data/r_translate.h" #include "p_3dmidtex.h" #include "d_net.h" @@ -3220,8 +3219,8 @@ FUNC(LS_GlassBreak) if (it != NULL) { it->GiveInventoryType (QuestItemClasses[28]); - it->GiveInventoryType (RUNTIME_CLASS(AUpgradeAccuracy)); - it->GiveInventoryType (RUNTIME_CLASS(AUpgradeStamina)); + it->GiveInventoryType (PClass::FindActor("UpgradeAccuracy")); + it->GiveInventoryType (PClass::FindActor("UpgradeStamina")); } } } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 7257eff95..d76832c59 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -942,7 +942,7 @@ AInventory *AActor::FirstInv () // //============================================================================ -bool AActor::DoUseInventory (AInventory *item) +bool AActor::UseInventory (AInventory *item) { // No using items if you're dead. if (health <= 0) @@ -973,23 +973,7 @@ DEFINE_ACTION_FUNCTION(AActor, UseInventory) { PARAM_SELF_PROLOGUE(AActor); PARAM_OBJECT(item, AInventory); - ACTION_RETURN_BOOL(self->DoUseInventory(item)); -} - -bool AActor::UseInventory(AInventory *item) -{ - IFVIRTUAL(AActor, UseInventory) - { - // Without the type cast this picks the 'void *' assignment... - VMValue params[2] = { (DObject*)this, (DObject*)item }; - VMReturn ret; - VMFrameStack stack; - int retval; - ret.IntAt(&retval); - stack.Call(func, params, 2, &ret, 1, nullptr); - return !!retval; - } - else return DoUseInventory(item); + ACTION_RETURN_BOOL(self->UseInventory(item)); } //=========================================================================== @@ -1304,6 +1288,13 @@ bool AActor::CheckLocalView (int playernum) const return false; } +DEFINE_ACTION_FUNCTION(AActor, CheckLocalView) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_INT(cp); + ACTION_RETURN_BOOL(self->CheckLocalView(cp)); +} + //============================================================================ // // AActor :: IsInsideVisibleAngles diff --git a/src/p_user.cpp b/src/p_user.cpp index 1033299e6..1ac60ba35 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -901,7 +901,7 @@ void APlayerPawn::RemoveInventory (AInventory *item) // //=========================================================================== -bool APlayerPawn::DoUseInventory (AInventory *item) +bool APlayerPawn::UseInventory (AInventory *item) { const PClass *itemtype = item->GetClass(); @@ -915,7 +915,7 @@ bool APlayerPawn::DoUseInventory (AInventory *item) return false; } - if (!Super::DoUseInventory (item)) + if (!Super::UseInventory (item)) { // Heretic and Hexen advance the inventory cursor if the use failed. // Should this behavior be retained? diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 6912755b4..2eb6cfec6 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -5822,10 +5822,30 @@ bool FxLocalVariable::RequestAddress(FCompileContext &ctx, bool *writable) ExpEmit FxLocalVariable::Emit(VMFunctionBuilder *build) { - ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); - ret.RegCount = ValueType->GetRegCount(); - if (AddressRequested) ret.Target = true; - return ret; + // 'Out' variables are actually pointers but this fact must be hidden to the script. + if (Variable->VarFlags & VARF_Out) + { + if (!AddressRequested) + { + ExpEmit reg(build, ValueType->GetRegType(), ValueType->GetRegCount()); + build->Emit(ValueType->GetLoadOp(), reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset)); + return reg; + } + else + { + if (RegOffset == 0) return ExpEmit(Variable->RegNum, REGT_POINTER, false, true); + ExpEmit reg(build, REGT_POINTER); + build->Emit(OP_ADDA_RK, reg.RegNum, Variable->RegNum, build->GetConstantInt(RegOffset)); + return reg; + } + } + else + { + ExpEmit ret(Variable->RegNum + RegOffset, Variable->ValueType->GetRegType(), false, true); + ret.RegCount = ValueType->GetRegCount(); + if (AddressRequested) ret.Target = true; + return ret; + } } @@ -7781,7 +7801,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) } FxExpression *x; - if (!(flag & VARF_Ref)) + if (!(flag & (VARF_Ref|VARF_Out))) { x = new FxTypeCast(ArgList[i], type, false); x = x->Resolve(ctx); @@ -7793,7 +7813,7 @@ FxExpression *FxVMFunctionCall::Resolve(FCompileContext& ctx) if (ArgList[i] != nullptr && ArgList[i]->ValueType != TypeNullPtr) { ArgList[i]->RequestAddress(ctx, &writable); - ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); + if (flag & VARF_Ref) ArgList[i]->ValueType = NewPointer(ArgList[i]->ValueType); // For a reference argument the types must match 100%. if (type != ArgList[i]->ValueType) { @@ -9917,10 +9937,15 @@ ExpEmit FxLocalVariableDeclaration::Emit(VMFunctionBuilder *build) { if (Init == nullptr) { - if (RegNum == -1) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + if (RegNum == -1) + { + if (!(VarFlags & VARF_Out)) RegNum = build->Registers[ValueType->GetRegType()].Get(RegCount); + else RegNum = build->Registers[REGT_POINTER].Get(1); + } } else { + assert(!(VarFlags & VARF_Out)); // 'out' variables should never be initialized, they can only exist as function parameters. ExpEmit emitval = Init->Emit(build); int regtype = emitval.RegType; diff --git a/src/scripting/thingdef_data.cpp b/src/scripting/thingdef_data.cpp index ee7cae76c..65a979edd 100644 --- a/src/scripting/thingdef_data.cpp +++ b/src/scripting/thingdef_data.cpp @@ -48,6 +48,7 @@ #include "p_terrain.h" #include "gstrings.h" #include "zstring.h" +#include "d_event.h" static TArray properties; static TArray AFTable; @@ -743,6 +744,12 @@ void InitThingdef() playerf = new PField("playeringame", parray, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&playeringame); GlobalSymbols.AddSymbol(playerf); + playerf = new PField("gameaction", TypeUInt8, VARF_Native | VARF_Static, (intptr_t)&gameaction); + GlobalSymbols.AddSymbol(playerf); + + playerf = new PField("consoleplayer", TypeSInt32, VARF_Native | VARF_Static | VARF_ReadOnly, (intptr_t)&consoleplayer); + GlobalSymbols.AddSymbol(playerf); + // Argh. It sucks when bad hacks need to be supported. WP_NOCHANGE is just a bogus pointer but it used everywhere as a special flag. // It cannot be defined as constant because constants can either be numbers or strings but nothing else, so the only 'solution' // is to create a static variable from it and reference that in the script. Yuck!!! diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index c454ced83..4eab47c1b 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2169,17 +2169,16 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool { auto type = DetermineType(c->Type(), p, f->Name, p->Type, false, false); int flags = 0; - if (p->Flags & ZCC_In) flags |= VARF_In; - if (p->Flags & ZCC_Out) flags |= VARF_Out; - if ((type->IsA(RUNTIME_CLASS(PStruct))) || (flags & VARF_Out)) + if (type->IsA(RUNTIME_CLASS(PStruct)) && type != TypeVector2 && type != TypeVector3) { - // 'out' parameters and all structs except vectors are passed by reference - if ((flags & VARF_Out) || (type != TypeVector2 && type != TypeVector3)) - { - type = NewPointer(type); - flags |= VARF_Ref; - } - else if (type == TypeVector2) + // Structs are being passed by pointer, but unless marked 'out' that pointer must be readonly. + type = NewPointer(type /*, !(p->Flags & ZCC_Out)*/); + flags |= VARF_Ref; + } + else if (type->GetRegType() != REGT_NIL) + { + if (p->Flags & ZCC_Out) flags |= VARF_Out; + if (type == TypeVector2) { elementcount = 2; } diff --git a/src/virtual.h b/src/virtual.h index 8485dec07..844c51d38 100644 --- a/src/virtual.h +++ b/src/virtual.h @@ -7,15 +7,14 @@ inline unsigned GetVirtualIndex(PClass *cls, const char *funcname) return VIndex; } -#define IFVIRTUAL(cls, funcname) \ +#define IFVIRTUALPTR(self, cls, funcname) \ static unsigned VIndex = ~0u; \ if (VIndex == ~0u) { \ VIndex = GetVirtualIndex(RUNTIME_CLASS(cls), #funcname); \ assert(VIndex != ~0u); \ } \ - auto clss = GetClass(); \ + auto clss = self->GetClass(); \ VMFunction *func = clss->Virtuals.Size() > VIndex? clss->Virtuals[VIndex] : nullptr; \ if (func != nullptr) - - +#define IFVIRTUAL(cls, funcname) IFVIRTUALPTR(this, cls, funcname) diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index c5052ab79..25d164d29 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -267,7 +267,6 @@ class Actor : Thinker native virtual native int TakeSpecialDamage (Actor inflictor, Actor source, int damage, Name damagetype); virtual native void Die(Actor source, Actor inflictor, int dmgflags = 0); virtual native bool Slam(Actor victim); - virtual native bool UseInventory(Inventory item); virtual native bool SpecialBlastHandling (Actor source, double strength); virtual native void Touch(Actor toucher); @@ -292,6 +291,7 @@ class Actor : Thinker native native void ClearBounce(); native TerrainDef GetFloorTerrain(); native Inventory DoDropItem(Class type, int dropamount, int chance); + native bool CheckLocalView(int consoleplayer); native void ExplodeMissile(line lin = null, Actor target = null); native void RestoreDamage(); @@ -378,6 +378,7 @@ class Actor : Thinker native native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); native Inventory DropInventory (Inventory item); + native bool UseInventory(Inventory item); native bool GiveAmmo (Class type, int amount); // DECORATE compatible functions diff --git a/wadsrc/static/zscript/constants.txt b/wadsrc/static/zscript/constants.txt index 5f86282a8..8180e6710 100644 --- a/wadsrc/static/zscript/constants.txt +++ b/wadsrc/static/zscript/constants.txt @@ -1015,3 +1015,25 @@ enum PaletteFlashFlags PF_ICE = 4, PF_HAZARD = 8, }; + +enum EGameAction +{ + ga_nothing, + ga_loadlevel, + ga_newgame, + ga_newgame2, + ga_recordgame, + ga_loadgame, + ga_loadgamehidecon, + ga_loadgameplaydemo, + ga_autoloadgame, + ga_savegame, + ga_autosave, + ga_playdemo, + ga_completed, + ga_slideshow, + ga_worlddone, + ga_screenshot, + ga_togglemap, + ga_fullconsole, +}; diff --git a/wadsrc/static/zscript/doom/scriptedmarine.txt b/wadsrc/static/zscript/doom/scriptedmarine.txt index 3987bc795..22766ac90 100644 --- a/wadsrc/static/zscript/doom/scriptedmarine.txt +++ b/wadsrc/static/zscript/doom/scriptedmarine.txt @@ -175,7 +175,7 @@ class ScriptedMarine : Actor // //============================================================================ - private bool GetWeaponStates(int weap, WeaponStates wstates) + private bool GetWeaponStates(int weap, out WeaponStates wstates) { static const statelabel MeleeNames[] = { diff --git a/wadsrc/static/zscript/shared/debris.txt b/wadsrc/static/zscript/shared/debris.txt index 24eae25be..3ffcea057 100644 --- a/wadsrc/static/zscript/shared/debris.txt +++ b/wadsrc/static/zscript/shared/debris.txt @@ -187,7 +187,7 @@ class Dirt6 : Actor // Stained glass ------------------------------------------------------------ -class GlassShard : Actor native +class GlassShard : Actor { Default { @@ -199,6 +199,16 @@ class GlassShard : Actor native BounceType "HexenCompat"; BounceFactor 0.3; } + + override void Tick() + { + Super.Tick(); + if (Vel.Z > 0 && Vel.Z < 0.5 && pos.z < floorz + 1) + { + Destroy (); + } + } + } class SGShard1 : GlassShard diff --git a/wadsrc/static/zscript/shared/inventory.txt b/wadsrc/static/zscript/shared/inventory.txt index d3e50d198..dbede839f 100644 --- a/wadsrc/static/zscript/shared/inventory.txt +++ b/wadsrc/static/zscript/shared/inventory.txt @@ -41,7 +41,8 @@ class Inventory : Actor native private native void A_RestoreSpecialDoomThing(); private native void A_RestoreSpecialThing1(); private native void A_RestoreSpecialThing2(); - + + virtual native bool TryPickup(in out Actor toucher); native bool, Actor CallTryPickup(Actor toucher); States(Actor, Overlay, Weapon, Item) diff --git a/wadsrc/static/zscript/strife/acolyte.txt b/wadsrc/static/zscript/strife/acolyte.txt index 6ae44f7f4..e5a019ea8 100644 --- a/wadsrc/static/zscript/strife/acolyte.txt +++ b/wadsrc/static/zscript/strife/acolyte.txt @@ -97,8 +97,8 @@ class Acolyte : StrifeHumanoid if (i == MAXPLAYERS) return; - // Make sure all the other blue acolytes are dead. - if (CheckBossDeath()) + // Make sure all the other blue acolytes are dead, but do this only once in case of simultaneous kills. + if (CheckBossDeath() && !players[i].mo.FindInventory("QuestItem7")) { players[i].mo.GiveInventoryType ("QuestItem7"); players[i].SetLogNumber (14); diff --git a/wadsrc/static/zscript/strife/strifeitems.txt b/wadsrc/static/zscript/strife/strifeitems.txt index 4d8e3d5e4..6d8037771 100644 --- a/wadsrc/static/zscript/strife/strifeitems.txt +++ b/wadsrc/static/zscript/strife/strifeitems.txt @@ -389,7 +389,7 @@ class Communicator : Inventory // Degnin Ore --------------------------------------------------------------- -class DegninOre : Inventory native +class DegninOre : Inventory { Default { @@ -421,6 +421,32 @@ class DegninOre : Inventory native BNG3 BCDEFGH 3 Bright; Stop; } + + override bool Use (bool pickup) + { + if (pickup) + { + return false; + } + else + { + Inventory drop; + + // Increase the amount by one so that when DropInventory decrements it, + // the actor will have the same number of beacons that he started with. + // When we return to UseInventory, it will take care of decrementing + // Amount again and disposing of this item if there are no more. + Amount++; + drop = Owner.DropInventory (self); + if (drop == NULL) + { + Amount--; + return false; + } + return true; + } + } + } // Gun Training ------------------------------------------------------------- @@ -446,7 +472,7 @@ class GunTraining : Inventory // Health Training ---------------------------------------------------------- -class HealthTraining : Inventory native +class HealthTraining : Inventory { Default { @@ -463,13 +489,23 @@ class HealthTraining : Inventory native HELT A -1; Stop; } + + override bool TryPickup (in out Actor toucher) + { + if (Super.TryPickup(toucher)) + { + toucher.GiveInventoryType ("GunTraining"); + toucher.A_GiveInventory("Coin", toucher.player.mo.accuracy*5 + 300); + return true; + } + return false; + } + } - - // Scanner ------------------------------------------------------------------ -class Scanner : PowerupGiver native +class Scanner : PowerupGiver { Default { @@ -488,11 +524,25 @@ class Scanner : PowerupGiver native PMUP AB 6; Loop; } + + override bool Use (bool pickup) + { + if (!level.AllMap) + { + if (Owner.CheckLocalView (consoleplayer)) + { + C_MidPrint("SmallFont", "$TXT_NEEDMAP"); + } + return false; + } + return Super.Use (pickup); + } + } // Prison Pass -------------------------------------------------------------- -class PrisonPass : Key native +class PrisonPass : Key { Default { @@ -506,6 +556,32 @@ class PrisonPass : Key native TOKN A -1; Stop; } + + override bool TryPickup (in out Actor toucher) + { + Super.TryPickup (toucher); + Door_Open(223, 16); + toucher.GiveInventoryType ("QuestItem10"); + return true; + } + + //============================================================================ + // + // APrisonPass :: SpecialDropAction + // + // Trying to make a monster that drops a prison pass turns it into an + // OpenDoor223 item instead. That means the only way to get it in Strife + // is through dialog, which is why it doesn't have its own sprite. + // + //============================================================================ + + override bool SpecialDropAction (Actor dropper) + { + Door_Open(223, 16); + Destroy (); + return true; + } + } //--------------------------------------------------------------------------- @@ -513,7 +589,7 @@ class PrisonPass : Key native // actions and cannot be held. ---------------------------------------------- //--------------------------------------------------------------------------- -class DummyStrifeItem : Inventory native +class DummyStrifeItem : Inventory { States { @@ -525,73 +601,221 @@ class DummyStrifeItem : Inventory native // Sound the alarm! --------------------------------------------------------- -class RaiseAlarm : DummyStrifeItem native +class RaiseAlarm : DummyStrifeItem { Default { Tag "$TAG_ALARM"; } + + override bool TryPickup (in out Actor toucher) + { + toucher.NoiseAlert (toucher); + + ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); + Actor spectre = Actor(it.Next()); + + if (spectre != NULL && spectre.health > 0 && toucher != spectre) + { + spectre.CurSector.SoundTarget = spectre.LastHeard = toucher; + spectre.target = toucher; + spectre.SetState (spectre.SeeState); + } + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + if (dropper.target != null) + { + dropper.target.NoiseAlert(dropper.target); + if (dropper.target.CheckLocalView(consoleplayer)) + { + A_Log("You Fool! You've set off the alarm."); + } + } + Destroy (); + return true; + } + } // Open door tag 222 -------------------------------------------------------- -class OpenDoor222 : DummyStrifeItem native +class OpenDoor222 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Open(222, 16); + GoAwayAndDie (); + return true; + } + } // Close door tag 222 ------------------------------------------------------- -class CloseDoor222 : DummyStrifeItem native +class CloseDoor222 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Close(222, 16); + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + Door_Close(222, 16); + if (dropper.target != null) + { + if (dropper.target.CheckLocalView(consoleplayer)) + { + A_Log("You're dead! You set off the alarm."); + } + dropper.target.NoiseAlert(dropper.target); + } + Destroy (); + return true; + } + } // Open door tag 224 -------------------------------------------------------- -class OpenDoor224 : DummyStrifeItem native +class OpenDoor224 : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + Door_Open(224, 16); + GoAwayAndDie (); + return true; + } + + override bool SpecialDropAction (Actor dropper) + { + Door_Open(224, 16); + Destroy (); + return true; + } + } // Ammo --------------------------------------------------------------------- -class AmmoFillup : DummyStrifeItem native +class AmmoFillup : DummyStrifeItem { Default { Tag "$TAG_AMMOFILLUP"; } + + override bool TryPickup (in out Actor toucher) + { + Inventory item = toucher.FindInventory("ClipOfBullets"); + if (item == NULL) + { + item = toucher.GiveInventoryType ("ClipOfBullets"); + if (item != NULL) + { + item.Amount = 50; + } + } + else if (item.Amount < 50) + { + item.Amount = 50; + } + else + { + return false; + } + GoAwayAndDie (); + return true; + } + } // Health ------------------------------------------------------------------- -class HealthFillup : DummyStrifeItem native +class HealthFillup : DummyStrifeItem { Default { Tag "$TAG_HEALTHFILLUP"; } + + override bool TryPickup (in out Actor toucher) + { + static const int skillhealths[] = { -100, -75, -50, -50, -100 }; + + int index = clamp(skill, 0,4); + if (!toucher.GiveBody (skillhealths[index])) + { + return false; + } + GoAwayAndDie (); + return true; + } + } // Upgrade Stamina ---------------------------------------------------------- -class UpgradeStamina : DummyStrifeItem native +class UpgradeStamina : DummyStrifeItem { Default { Inventory.Amount 10; Inventory.MaxAmount 100; } + + override bool TryPickup (in out Actor toucher) + { + if (toucher.player == NULL) + return false; + + toucher.player.mo.stamina += Amount; + if (toucher.player.mo.stamina >= MaxAmount) + toucher.player.mo.stamina = MaxAmount; + + toucher.GiveBody (-100); + GoAwayAndDie (); + return true; + } + } // Upgrade Accuracy --------------------------------------------------------- -class UpgradeAccuracy : DummyStrifeItem native +class UpgradeAccuracy : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + if (toucher.player == NULL || toucher.player.mo.accuracy >= 100) + return false; + toucher.player.mo.accuracy += 10; + GoAwayAndDie (); + return true; + } + } // Start a slideshow -------------------------------------------------------- -class SlideshowStarter : DummyStrifeItem native +class SlideshowStarter : DummyStrifeItem { + override bool TryPickup (in out Actor toucher) + { + gameaction = ga_slideshow; + if (level.levelnum == 10) + { + toucher.GiveInventoryType ("QuestItem17"); + } + GoAwayAndDie (); + return true; + } + }