diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eddf2d9e9..885b9fd91 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -861,9 +861,6 @@ set( NOT_COMPILED_SOURCE_FILES sc_man_scanner.re g_hexen/a_heresiarch.cpp g_hexen/a_spike.cpp - g_strife/a_oracle.cpp - g_strife/a_programmer.cpp - g_strife/a_rebels.cpp g_strife/a_sentinel.cpp g_strife/a_stalker.cpp g_strife/a_strifeitems.cpp diff --git a/src/actor.h b/src/actor.h index 06a5e9f11..8e1b16739 100644 --- a/src/actor.h +++ b/src/actor.h @@ -696,7 +696,7 @@ public: bool UseInventory(AInventory *item); // Tosses an item out of the inventory. - virtual AInventory *DropInventory (AInventory *item); + AInventory *DropInventory (AInventory *item); // Removes all items from the inventory. void ClearInventory(); diff --git a/src/g_strife/a_oracle.cpp b/src/g_strife/a_oracle.cpp deleted file mode 100644 index f49849922..000000000 --- a/src/g_strife/a_oracle.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* -#include "actor.h" -#include "a_action.h" -#include "a_strifeglobal.h" -#include "p_enemy.h" -#include "r_defs.h" -#include "vm.h" -*/ - - -DEFINE_ACTION_FUNCTION(AActor, A_WakeOracleSpectre) -{ - PARAM_SELF_PROLOGUE(AActor); - - TThinkerIterator it(NAME_AlienSpectre3); - AActor *spectre = it.Next(); - - if (spectre != NULL && spectre->health > 0 && self->target != spectre) - { - spectre->Sector->SoundTarget = spectre->LastHeard = self->LastHeard; - spectre->target = self->target; - spectre->SetState (spectre->SeeState); - } - return 0; -} - diff --git a/src/g_strife/a_programmer.cpp b/src/g_strife/a_programmer.cpp deleted file mode 100644 index a02848dd2..000000000 --- a/src/g_strife/a_programmer.cpp +++ /dev/null @@ -1,141 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "a_strifeglobal.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ -static FRandom pr_prog ("Programmer"); - -// The Programmer level ending thing ---------------------------------------- -// [RH] I took some liberties to make this "cooler" than it was in Strife. - -class AProgLevelEnder : public AInventory -{ - DECLARE_CLASS (AProgLevelEnder, AInventory) -public: - void Tick (); - PalEntry GetBlend (); -}; - -IMPLEMENT_CLASS(AProgLevelEnder, false, false) - -//============================================================================ -// -// AProgLevelEnder :: Tick -// -// Fade to black, end the level, then unfade. -// -//============================================================================ - -void AProgLevelEnder::Tick () -{ - if (special2 == 0) - { // fade out over .66 second - special1 += 255 / (TICRATE*2/3); - if (++special1 >= 255) - { - special1 = 255; - special2 = 1; - G_ExitLevel (0, false); - } - } - else - { // fade in over two seconds - special1 -= 255 / (TICRATE*2); - if (special1 <= 0) - { - Destroy (); - } - } -} - -//============================================================================ -// -// AProgLevelEnder :: GetBlend -// -//============================================================================ - -PalEntry AProgLevelEnder::GetBlend () -{ - return PalEntry ((BYTE)special1, 0, 0, 0); -} - -//============================================================================ -// -// A_ProgrammerMelee -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee) -{ - PARAM_SELF_PROLOGUE(AActor); - - int damage; - - if (self->target == NULL) - return 0; - - A_FaceTarget (self); - - if (!self->CheckMeleeRange ()) - return 0; - - S_Sound (self, CHAN_WEAPON, "programmer/clank", 1, ATTN_NORM); - - damage = ((pr_prog() % 10) + 1) * 6; - int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee); - P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self); - return 0; -} - -//============================================================================ -// -// A_SpawnProgrammerBase -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *foo = Spawn("ProgrammerBase", self->PosPlusZ(24.), ALLOW_REPLACE); - if (foo != NULL) - { - foo->Angles.Yaw = self->Angles.Yaw + 180. + pr_prog.Random2() * (360. / 1024.); - foo->VelFromAngle(); - foo->Vel.Z = pr_prog() / 128.; - } - return 0; -} - -//============================================================================ -// -// A_ProgrammerDeath -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerDeath) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (!CheckBossDeath (self)) - return 0; - - for (int i = 0; i < MAXPLAYERS; ++i) - { - if (playeringame[i] && players[i].health > 0) - { - players[i].mo->GiveInventoryType (RUNTIME_CLASS(AProgLevelEnder)); - break; - } - } - // the sky change scripts are now done as special actions in MAPINFO - A_BossDeath(self); - return 0; -} diff --git a/src/g_strife/a_rebels.cpp b/src/g_strife/a_rebels.cpp deleted file mode 100644 index d3d68153f..000000000 --- a/src/g_strife/a_rebels.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* -#include "actor.h" -#include "m_random.h" -#include "a_action.h" -#include "p_local.h" -#include "p_enemy.h" -#include "s_sound.h" -#include "gi.h" -#include "a_sharedglobal.h" -#include "a_strifeglobal.h" -#include "vm.h" -#include "doomstat.h" -*/ - -static FRandom pr_shootgun ("ShootGun"); - -//============================================================================ -// -// A_ShootGun -// -//============================================================================ - -DEFINE_ACTION_FUNCTION(AActor, A_ShootGun) -{ - PARAM_SELF_PROLOGUE(AActor); - - DAngle pitch; - - if (self->target == NULL) - return 0; - - S_Sound (self, CHAN_WEAPON, "monsters/rifle", 1, ATTN_NORM); - A_FaceTarget (self); - pitch = P_AimLineAttack (self, self->Angles.Yaw, MISSILERANGE); - P_LineAttack (self, self->Angles.Yaw + pr_shootgun.Random2() * (11.25 / 256), - MISSILERANGE, pitch, - 3*(pr_shootgun() % 5 + 1), NAME_Hitscan, NAME_StrifePuff); - return 0; -} - -// Teleporter Beacon -------------------------------------------------------- - -class ATeleporterBeacon : public AInventory -{ - DECLARE_CLASS (ATeleporterBeacon, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(ATeleporterBeacon, false, false) - -bool ATeleporterBeacon::Use (bool pickup) -{ - 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; - } - else - { - drop->SetState(drop->FindState(NAME_Drop)); - drop->target = Owner; - return true; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_Beacon) -{ - PARAM_SELF_PROLOGUE(AActor); - - AActor *owner = self->target; - AActor *rebel; - - rebel = Spawn("Rebel1", self->PosAtZ(self->floorz), ALLOW_REPLACE); - if (!P_TryMove (rebel, rebel->Pos(), true)) - { - rebel->Destroy (); - return 0; - } - // Once the rebels start teleporting in, you can't pick up the beacon anymore. - self->flags &= ~MF_SPECIAL; - static_cast(self)->DropTime = 0; - // Set up the new rebel. - rebel->threshold = rebel->DefThreshold; - rebel->target = NULL; - rebel->flags4 |= MF4_INCOMBAT; - rebel->LastHeard = owner; // Make sure the rebels look for targets - if (deathmatch) - { - rebel->health *= 2; - } - if (owner != NULL) - { - // Rebels are the same color as their owner (but only in multiplayer) - if (multiplayer) - { - rebel->Translation = owner->Translation; - } - rebel->SetFriendPlayer(owner->player); - // Set the rebel's target to whatever last hurt the player, so long as it's not - // one of the player's other rebels. - if (owner->target != NULL && !rebel->IsFriend (owner->target)) - { - rebel->target = owner->target; - } - } - - rebel->SetState (rebel->SeeState); - rebel->Angles.Yaw = self->Angles.Yaw; - P_SpawnTeleportFog(rebel, rebel->Vec3Angle(20., self->Angles.Yaw, 0), false, true); - if (--self->health < 0) - { - self->SetState(self->FindState(NAME_Death)); - } - return 0; -} diff --git a/src/g_strife/a_strifeitems.cpp b/src/g_strife/a_strifeitems.cpp index 0f1132cbd..aa48d9839 100644 --- a/src/g_strife/a_strifeitems.cpp +++ b/src/g_strife/a_strifeitems.cpp @@ -180,8 +180,18 @@ IMPLEMENT_CLASS(ARaiseAlarm, false, false) bool ARaiseAlarm::TryPickup (AActor *&toucher) { P_NoiseAlert (toucher, toucher); - VMFrameStack stack1, *stack = &stack1; - CALL_ACTION(A_WakeOracleSpectre, 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; } diff --git a/src/g_strife/a_strifestuff.cpp b/src/g_strife/a_strifestuff.cpp index e8ae59c18..0a2f5c5fd 100644 --- a/src/g_strife/a_strifestuff.cpp +++ b/src/g_strife/a_strifestuff.cpp @@ -24,9 +24,6 @@ #include "vm.h" // Include all the other Strife stuff here to reduce compile time -#include "a_oracle.cpp" -#include "a_programmer.cpp" -#include "a_rebels.cpp" #include "a_sentinel.cpp" #include "a_stalker.cpp" #include "a_strifeitems.cpp" diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 8424caee8..c85b8bbbc 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -1018,6 +1018,13 @@ AInventory *AActor::DropInventory (AInventory *item) return drop; } +DEFINE_ACTION_FUNCTION(AActor, DropInventory) +{ + PARAM_SELF_PROLOGUE(AActor); + PARAM_OBJECT(item, AInventory); + ACTION_RETURN_OBJECT(self->DropInventory(item)); +} + //============================================================================ // // AActor :: FindInventory diff --git a/wadsrc/static/zscript/actor.txt b/wadsrc/static/zscript/actor.txt index 2d2725d1e..35dee8fba 100644 --- a/wadsrc/static/zscript/actor.txt +++ b/wadsrc/static/zscript/actor.txt @@ -372,12 +372,13 @@ class Actor : Thinker native native void PlayActiveSound(); native void Howl(); - // DECORATE compatible functions native bool CheckClass(class checkclass, int ptr_select = AAPTR_DEFAULT, bool match_superclass = false); native Inventory FindInventory(class itemtype, bool subclass = false); native Inventory GiveInventoryType(class itemtype); + native Inventory DropInventory (Inventory item); native bool GiveAmmo (Class type, int amount); + // DECORATE compatible functions native int CountInv(class itemtype, int ptr_select = AAPTR_DEFAULT); native double GetDistance(bool checkz, int ptr = AAPTR_TARGET); native double GetAngle(int flags, int ptr = AAPTR_DEFAULT); @@ -701,7 +702,6 @@ class Actor : Thinker native native void A_ClearLastHeard(); native bool A_SelectWeapon(class whichweapon, int flags = 0); native void A_ClassBossHealth(); - native void A_ShootGun(); native void A_RocketInFlight(); native void A_Bang4Cloud(); native void A_DropFire(); diff --git a/wadsrc/static/zscript/strife/oracle.txt b/wadsrc/static/zscript/strife/oracle.txt index 6023629c2..740a7b69a 100644 --- a/wadsrc/static/zscript/strife/oracle.txt +++ b/wadsrc/static/zscript/strife/oracle.txt @@ -19,8 +19,6 @@ class Oracle : Actor DropItem "Meat"; } - native void A_WakeOracleSpectre (); - States { Spawn: @@ -35,4 +33,19 @@ class Oracle : Actor ORCL Q -1; Stop; } + + void A_WakeOracleSpectre () + { + ThinkerIterator it = ThinkerIterator.Create("AlienSpectre3"); + Actor spectre = Actor(it.Next()); + + if (spectre != NULL && spectre.health > 0 && self.target != spectre) + { + spectre.CurSector.SoundTarget = spectre.LastHeard = self.LastHeard; + spectre.target = self.target; + spectre.SetState (spectre.SeeState); + } + } + + } diff --git a/wadsrc/static/zscript/strife/programmer.txt b/wadsrc/static/zscript/strife/programmer.txt index 9ef9bdeb0..3fa34b659 100644 --- a/wadsrc/static/zscript/strife/programmer.txt +++ b/wadsrc/static/zscript/strife/programmer.txt @@ -33,10 +33,6 @@ class Programmer : Actor DropItem "Sigil1"; } - native void A_ProgrammerMelee (); - native void A_SpawnProgrammerBase (); - native void A_ProgrammerDeath (); - States { Spawn: @@ -80,6 +76,69 @@ class Programmer : Actor Stop; } + //============================================================================ + // + // A_ProgrammerMelee + // + //============================================================================ + + void A_ProgrammerMelee () + { + if (target == null) + return; + + A_FaceTarget (); + + if (!CheckMeleeRange ()) + return; + + A_PlaySound("programmer/clank", CHAN_WEAPON); + + int damage = ((random[Programmer]() % 10) + 1) * 6; + int newdam = DamageMobj (self, self, damage, 'Melee'); + target.TraceBleed (newdam > 0 ? newdam : damage, self); + } + + //============================================================================ + // + // A_SpawnProgrammerBase + // + //============================================================================ + + void A_SpawnProgrammerBase () + { + Actor foo = Spawn("ProgrammerBase", Pos + (0,0,24), ALLOW_REPLACE); + if (foo != null) + { + foo.Angle = Angle + 180. + Random2[Programmer]() * (360. / 1024.); + foo.VelFromAngle(); + foo.Vel.Z = random[Programmer]() / 128.; + } + } + + //============================================================================ + // + // A_ProgrammerDeath + // + //============================================================================ + + void A_ProgrammerDeath () + { + if (!CheckBossDeath ()) + return; + + for (int i = 0; i < MAXPLAYERS; ++i) + { + if (playeringame[i] && players[i].health > 0) + { + players[i].mo.GiveInventoryType ("ProgLevelEnder"); + break; + } + } + // the sky change scripts are now done as special actions in MAPINFO + A_BossDeath(); + } + //============================================================================ // // A_SpotLightning @@ -88,10 +147,10 @@ class Programmer : Actor void A_SpotLightning() { - if (target == NULL) return; + if (target == null) return; Actor spot = Spawn("SpectralLightningSpot", (target.pos.xy, target.floorz), ALLOW_REPLACE); - if (spot != NULL) + if (spot != null) { spot.threshold = 25; spot.target = self; @@ -127,10 +186,52 @@ class ProgrammerBase : Actor // The Programmer level ending thing ---------------------------------------- -class ProgLevelEnder : Inventory native +class ProgLevelEnder : Inventory { Default { +INVENTORY.UNDROPPABLE } + + + //============================================================================ + // + // AProgLevelEnder :: Tick + // + // Fade to black, end the level, then unfade. + // + //============================================================================ + + override void Tick () + { + if (special2 == 0) + { // fade out over .66 second + special1 += 255 / (TICRATE*2/3); + if (++special1 >= 255) + { + special1 = 255; + special2 = 1; + Exit_Normal(0); + } + } + else + { // fade in over two seconds + special1 -= 255 / (TICRATE*2); + if (special1 <= 0) + { + Destroy (); + } + } + } + + //============================================================================ + // + // AProgLevelEnder :: GetBlend + // + //============================================================================ + + override Color GetBlend () + { + return Color(special1, 0, 0, 0); + } } diff --git a/wadsrc/static/zscript/strife/rebels.txt b/wadsrc/static/zscript/strife/rebels.txt index d9e65560f..24deea25b 100644 --- a/wadsrc/static/zscript/strife/rebels.txt +++ b/wadsrc/static/zscript/strife/rebels.txt @@ -107,7 +107,7 @@ class Rebel6 : Rebel // Teleporter Beacon -------------------------------------------------------- -class TeleporterBeacon : Inventory native +class TeleporterBeacon : Inventory { Default { @@ -122,8 +122,6 @@ class TeleporterBeacon : Inventory native Inventory.PickupMessage "$TXT_BEACON"; } - native void A_Beacon (); - States { Spawn: @@ -137,4 +135,73 @@ class TeleporterBeacon : Inventory native BEAC A 1 A_FadeOut(0.015); Loop; } + + // Teleporter Beacon -------------------------------------------------------- + + override bool Use (bool pickup) + { + // 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 self item if there are no more. + Amount++; + Inventory drop = Owner.DropInventory (self); + if (drop == null) + { + Amount--; + return false; + } + else + { + drop.SetStateLabel("Drop"); + drop.target = Owner; + return true; + } + } + + void A_Beacon() + { + Actor owner = target; + Actor rebel = Spawn("Rebel1", (pos.xy, floorz), ALLOW_REPLACE); + if (!rebel.TryMove (rebel.Pos.xy, true)) + { + rebel.Destroy (); + return; + } + // Once the rebels start teleporting in, you can't pick up the beacon anymore. + bSpecial = false; + Inventory(self).DropTime = 0; + // Set up the new rebel. + rebel.threshold = rebel.DefThreshold; + rebel.target = null; + rebel.bInCombat = true; + rebel.LastHeard = owner; // Make sure the rebels look for targets + if (deathmatch) + { + rebel.health *= 2; + } + if (owner != null) + { + // Rebels are the same color as their owner (but only in multiplayer) + if (multiplayer) + { + rebel.Translation = owner.Translation; + } + rebel.SetFriendPlayer(owner.player); + // Set the rebel's target to whatever last hurt the player, so long as it's not + // one of the player's other rebels. + if (owner.target != null && !rebel.IsFriend (owner.target)) + { + rebel.target = owner.target; + } + } + + rebel.SetState (rebel.SeeState); + rebel.Angle = Angle; + rebel.SpawnTeleportFog(rebel.Vec3Angle(20., Angle, 0), false, true); + if (--health < 0) + { + SetStateLabel("Death"); + } + } } \ No newline at end of file diff --git a/wadsrc/static/zscript/strife/strifehumanoid.txt b/wadsrc/static/zscript/strife/strifehumanoid.txt index 7ac776026..7cec969ea 100644 --- a/wadsrc/static/zscript/strife/strifehumanoid.txt +++ b/wadsrc/static/zscript/strife/strifehumanoid.txt @@ -56,3 +56,21 @@ class FireDroplet : Actor } +extend class Actor +{ + //============================================================================ + // + // A_ShootGun + // + //============================================================================ + + void A_ShootGun() + { + if (!target) return; + A_PlaySound ("monsters/rifle", CHAN_WEAPON); + A_FaceTarget (); + double pitch = AimLineAttack (angle, MISSILERANGE); + LineAttack (Angle + Random2[ShootGun]() * (11.25 / 256), MISSILERANGE, pitch, 3*(random[ShootGun]() % 5 + 1), 'Hitscan', "StrifePuff"); + } + +} \ No newline at end of file