mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-10 14:51:51 +00:00
- scriptified Hexen's Banishment Device.
This commit is contained in:
parent
ebd2c27e0a
commit
d4427e696d
6 changed files with 149 additions and 210 deletions
|
@ -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
|
||||
|
|
|
@ -1540,15 +1540,28 @@ DEFINE_ACTION_FUNCTION(DObject, G_PickDeathmatchStart)
|
|||
{
|
||||
PARAM_PROLOGUE;
|
||||
unsigned int selections = deathmatchstarts.Size();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -267,3 +267,9 @@ struct TerrainDef native
|
|||
native double Friction;
|
||||
native double MoveFactor;
|
||||
};
|
||||
|
||||
enum EPickStart
|
||||
{
|
||||
PPS_FORCERANDOM = 1,
|
||||
PPS_NOBLOCKINGCHECK = 2,
|
||||
}
|
||||
|
|
|
@ -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<Actor> 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue