From d4427e696d12efa08b0de90db9ff22640d4c0bc6 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 28 Nov 2016 01:30:36 +0100 Subject: [PATCH] - scriptified Hexen's Banishment Device. --- src/CMakeLists.txt | 1 - src/g_game.cpp | 19 +- src/g_hexen/a_hexenmisc.cpp | 1 - src/g_hexen/a_teleportother.cpp | 198 ------------------ wadsrc/static/zscript/base.txt | 6 + wadsrc/static/zscript/hexen/teleportother.txt | 134 +++++++++++- 6 files changed, 149 insertions(+), 210 deletions(-) delete mode 100644 src/g_hexen/a_teleportother.cpp diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40d227fa4..553a66c12 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_hexen/a_teleportother.cpp g_strife/a_acolyte.cpp g_strife/a_alienspectres.cpp g_strife/a_coin.cpp diff --git a/src/g_game.cpp b/src/g_game.cpp index 350669cfe..b5729283e 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1540,15 +1540,28 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart) { PARAM_PROLOGUE; unsigned int selections = deathmatchstarts.Size(); - unsigned int i = pr_dmspawn() % selections; + DVector3 pos; + int angle; + if (selections == 0) + { + angle = INT_MAX; + pos = DVector3(0, 0, 0); + } + else + { + unsigned int i = pr_dmspawn() % selections; + angle = deathmatchstarts[i].angle; + pos = deathmatchstarts[i].pos; + } + if (numret > 1) { - ret[1].SetInt(deathmatchstarts[i].angle); + ret[1].SetInt(angle); numret = 2; } if (numret > 0) { - ret[0].SetVector(deathmatchstarts[i].pos); + ret[0].SetVector(pos); } return numret; } diff --git a/src/g_hexen/a_hexenmisc.cpp b/src/g_hexen/a_hexenmisc.cpp index 4cfd359f8..f871e82d9 100644 --- a/src/g_hexen/a_hexenmisc.cpp +++ b/src/g_hexen/a_hexenmisc.cpp @@ -26,4 +26,3 @@ // Include all the Hexen stuff here to reduce compile time #include "a_heresiarch.cpp" #include "a_spike.cpp" -#include "a_teleportother.cpp" diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp deleted file mode 100644 index 0e7dd018d..000000000 --- a/src/g_hexen/a_teleportother.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/* -#include "info.h" -#include "a_pickups.h" -#include "a_artifacts.h" -#include "gstrings.h" -#include "p_local.h" -#include "s_sound.h" -#include "p_lnspec.h" -#include "m_random.h" -#include "vm.h" -#include "g_level.h" -#include "doomstat.h" -*/ - -#define TELEPORT_LIFE 1 - -static FRandom pr_telestarts ("TeleStarts"); -static FRandom pr_teledm ("TeleDM"); - -void A_TeloSpawnA (AActor *); -void A_TeloSpawnB (AActor *); -void A_TeloSpawnC (AActor *); -void A_TeloSpawnD (AActor *); -void A_CheckTeleRing (AActor *); -void P_TeleportToPlayerStarts (AActor *victim); -void P_TeleportToDeathmatchStarts (AActor *victim); - -// Teleport Other Artifact -------------------------------------------------- - -class AArtiTeleportOther : public AInventory -{ - DECLARE_CLASS (AArtiTeleportOther, AInventory) -public: - bool Use (bool pickup); -}; - -IMPLEMENT_CLASS(AArtiTeleportOther, false, false) - -// Teleport Other FX -------------------------------------------------------- - -class ATelOtherFX1 : public AActor -{ - DECLARE_CLASS (ATelOtherFX1, AActor) -public: - int DoSpecialDamage (AActor *target, int damage, FName damagetype); -}; - -IMPLEMENT_CLASS(ATelOtherFX1, false, false) - -static void TeloSpawn (AActor *source, const char *type) -{ - AActor *fx; - - fx = Spawn (type, source->Pos(), ALLOW_REPLACE); - if (fx) - { - fx->special1 = TELEPORT_LIFE; // Lifetime countdown - fx->Angles.Yaw = source->Angles.Yaw; - fx->target = source->target; - fx->Vel = source->Vel / 2; - } -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnA) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX2"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnB) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX3"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnC) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX4"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnD) -{ - PARAM_SELF_PROLOGUE(AActor); - TeloSpawn (self, "TelOtherFX5"); - return 0; -} - -DEFINE_ACTION_FUNCTION(AActor, A_CheckTeleRing) -{ - PARAM_SELF_PROLOGUE(AActor); - - if (self->special1-- <= 0) - { - self->SetState (self->FindState(NAME_Death)); - } - return 0; -} - -//=========================================================================== -// -// Activate Teleport Other -// -//=========================================================================== - -bool AArtiTeleportOther::Use (bool pickup) -{ - AActor *mo; - - mo = P_SpawnPlayerMissile (Owner, RUNTIME_CLASS(ATelOtherFX1)); - if (mo) - { - mo->target = Owner; - } - return true; -} - -//=========================================================================== -// -// Perform Teleport Other -// -//=========================================================================== - -int ATelOtherFX1::DoSpecialDamage (AActor *target, int damage, FName damagetype) -{ - if ((target->flags3 & MF3_ISMONSTER || target->player != NULL) && - !(target->flags2 & MF2_BOSS) && - !(target->flags3 & MF3_NOTELEOTHER)) - { - if (target->player) - { - if (deathmatch) - P_TeleportToDeathmatchStarts (target); - else - P_TeleportToPlayerStarts (target); - } - else - { - // If death action, run it upon teleport - if (target->flags3 & MF3_ISMONSTER && target->special) - { - target->RemoveFromHash (); - P_ExecuteSpecial(target->special, NULL, level.flags & LEVEL_ACTOWNSPECIAL - ? target : (AActor *)(this->target), false, target->args[0], target->args[1], - target->args[2], target->args[3], target->args[4]); - target->special = 0; - } - - // Send all monsters to deathmatch spots - P_TeleportToDeathmatchStarts (target); - } - } - return -1; -} - -//=========================================================================== -// -// P_TeleportToPlayerStarts -// -//=========================================================================== - -void P_TeleportToPlayerStarts (AActor *victim) -{ - DVector3 dest; - - FPlayerStart *start = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); - dest = start->pos; - dest.Z = ONFLOORZ; - P_Teleport (victim, dest, (double)start->angle, TELF_SOURCEFOG | TELF_DESTFOG); -} - -//=========================================================================== -// -// P_TeleportToDeathmatchStarts -// -//=========================================================================== - -void P_TeleportToDeathmatchStarts (AActor *victim) -{ - unsigned int i, selections; - DVector3 dest; - - selections = deathmatchstarts.Size (); - if (selections > 0) - { - i = pr_teledm() % selections; - dest = deathmatchstarts[i].pos; - dest.Z = ONFLOORZ; - P_Teleport (victim, dest, (double)deathmatchstarts[i].angle, TELF_SOURCEFOG | TELF_DESTFOG); - } - else - { - P_TeleportToPlayerStarts (victim); - } -} diff --git a/wadsrc/static/zscript/base.txt b/wadsrc/static/zscript/base.txt index 08d655caf..3a96cbbcb 100644 --- a/wadsrc/static/zscript/base.txt +++ b/wadsrc/static/zscript/base.txt @@ -267,3 +267,9 @@ struct TerrainDef native native double Friction; native double MoveFactor; }; + +enum EPickStart +{ + PPS_FORCERANDOM = 1, + PPS_NOBLOCKINGCHECK = 2, +} diff --git a/wadsrc/static/zscript/hexen/teleportother.txt b/wadsrc/static/zscript/hexen/teleportother.txt index 2de144d5f..f7be0ebff 100644 --- a/wadsrc/static/zscript/hexen/teleportother.txt +++ b/wadsrc/static/zscript/hexen/teleportother.txt @@ -1,7 +1,7 @@ // Teleport Other Artifact -------------------------------------------------- -class ArtiTeleportOther : Inventory native +class ArtiTeleportOther : Inventory { Default { @@ -22,13 +22,29 @@ class ArtiTeleportOther : Inventory native TELO ABCD 5; Loop; } + + //=========================================================================== + // + // Activate Teleport Other + // + //=========================================================================== + + override bool Use (bool pickup) + { + Owner.SpawnPlayerMissile ("TelOtherFX1"); + return true; + } + + } // Teleport Other FX -------------------------------------------------------- -class TelOtherFX1 : Actor native +class TelOtherFX1 : Actor { + const TELEPORT_LIFE = 1; + Default { Damage 10001; @@ -41,11 +57,6 @@ class TelOtherFX1 : Actor native Speed 20; } - native void A_TeloSpawnA(); - native void A_TeloSpawnB(); - native void A_TeloSpawnC(); - native void A_TeloSpawnD(); - native void A_CheckTeleRing (); States { @@ -63,6 +74,115 @@ class TelOtherFX1 : Actor native TRNG E 3 Bright; Stop; } + + private void TeloSpawn (class type) + { + Actor fx = Spawn (type, pos, ALLOW_REPLACE); + if (fx) + { + fx.special1 = TELEPORT_LIFE; // Lifetime countdown + fx.angle = angle; + fx.target = target; + fx.Vel = Vel / 2; + } + } + + void A_TeloSpawnA() + { + TeloSpawn ("TelOtherFX2"); + } + + void A_TeloSpawnB() + { + TeloSpawn ("TelOtherFX3"); + } + + void A_TeloSpawnC() + { + TeloSpawn ("TelOtherFX4"); + } + + void A_TeloSpawnD() + { + TeloSpawn ("TelOtherFX5"); + } + + void A_CheckTeleRing () + { + if (self.special1-- <= 0) + { + self.SetStateLabel("Death"); + } + } + + //=========================================================================== + // + // Perform Teleport Other + // + //=========================================================================== + + override int DoSpecialDamage (Actor target, int damage, Name damagetype) + { + if ((target.bIsMonster || target.player != NULL) && + !target.bBoss && !target.bNoTeleOther) + { + if (target.player) + { + if (deathmatch) + P_TeleportToDeathmatchStarts (target); + else + P_TeleportToPlayerStarts (target); + } + else + { + // If death action, run it upon teleport + if (target.bIsMonster && target.special) + { + target.RemoveFromHash (); + Actor caller = level.ActOwnSpecial? target : self.target; + caller.A_CallSpecial(target.special, target.args[0], target.args[1], target.args[2], target.args[3], target.args[4]); + target.special = 0; + } + + // Send all monsters to deathmatch spots + P_TeleportToDeathmatchStarts (target); + } + } + return -1; + } + + //=========================================================================== + // + // P_TeleportToPlayerStarts + // + //=========================================================================== + + private static void P_TeleportToPlayerStarts (Actor victim) + { + Vector3 dest; + double destAngle; + + [dest, destAngle] = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK); + dest.Z = ONFLOORZ; + victim.Teleport ((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); + } + + //=========================================================================== + // + // P_TeleportToDeathmatchStarts + // + //=========================================================================== + + private void P_TeleportToDeathmatchStarts (Actor victim) + { + Vector3 dest; + double destAngle; + + [dest, destAngle] = G_PickDeathmatchStart(); + if (destAngle < 65536) victim.Teleport((dest.xy, ONFLOORZ), destangle, TELF_SOURCEFOG | TELF_DESTFOG); + else P_TeleportToPlayerStarts(victim); + } + }