mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-16 07:32:20 +00:00
0c8e4c37d9
SVN r3750 (trunk)
193 lines
4.7 KiB
C++
193 lines
4.7 KiB
C++
/*
|
|
#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 "thingdef/thingdef.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)
|
|
|
|
// Teleport Other FX --------------------------------------------------------
|
|
|
|
class ATelOtherFX1 : public AActor
|
|
{
|
|
DECLARE_CLASS (ATelOtherFX1, AActor)
|
|
public:
|
|
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
|
|
};
|
|
|
|
IMPLEMENT_CLASS (ATelOtherFX1)
|
|
|
|
static void TeloSpawn (AActor *source, const char *type)
|
|
{
|
|
AActor *fx;
|
|
|
|
fx = Spawn (type, source->x, source->y, source->z, ALLOW_REPLACE);
|
|
if (fx)
|
|
{
|
|
fx->special1 = TELEPORT_LIFE; // Lifetime countdown
|
|
fx->angle = source->angle;
|
|
fx->target = source->target;
|
|
fx->velx = source->velx >> 1;
|
|
fx->vely = source->vely >> 1;
|
|
fx->velz = source->velz >> 1;
|
|
}
|
|
}
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnA)
|
|
{
|
|
TeloSpawn (self, "TelOtherFX2");
|
|
}
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnB)
|
|
{
|
|
TeloSpawn (self, "TelOtherFX3");
|
|
}
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnC)
|
|
{
|
|
TeloSpawn (self, "TelOtherFX4");
|
|
}
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_TeloSpawnD)
|
|
{
|
|
TeloSpawn (self, "TelOtherFX5");
|
|
}
|
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_CheckTeleRing)
|
|
{
|
|
if (self->special1-- <= 0)
|
|
{
|
|
self->SetState (self->FindState(NAME_Death));
|
|
}
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// 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)
|
|
{
|
|
fixed_t destX,destY;
|
|
angle_t destAngle;
|
|
|
|
FPlayerStart *start = G_PickPlayerStart(0, PPS_FORCERANDOM | PPS_NOBLOCKINGCHECK);
|
|
destX = start->x;
|
|
destY = start->y;
|
|
destAngle = ANG45 * (start->angle/45);
|
|
P_Teleport (victim, destX, destY, ONFLOORZ, destAngle, true, true, false);
|
|
}
|
|
|
|
//===========================================================================
|
|
//
|
|
// P_TeleportToDeathmatchStarts
|
|
//
|
|
//===========================================================================
|
|
|
|
void P_TeleportToDeathmatchStarts (AActor *victim)
|
|
{
|
|
unsigned int i, selections;
|
|
fixed_t destX,destY;
|
|
angle_t destAngle;
|
|
|
|
selections = deathmatchstarts.Size ();
|
|
if (selections > 0)
|
|
{
|
|
i = pr_teledm() % selections;
|
|
destX = deathmatchstarts[i].x;
|
|
destY = deathmatchstarts[i].y;
|
|
destAngle = ANG45 * (deathmatchstarts[i].angle/45);
|
|
P_Teleport (victim, destX, destY, ONFLOORZ, destAngle, true, true, false);
|
|
}
|
|
else
|
|
{
|
|
P_TeleportToPlayerStarts (victim);
|
|
}
|
|
}
|