2008-09-15 14:11:05 +00:00
|
|
|
/*
|
2006-02-24 04:48:15 +00:00
|
|
|
#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"
|
2008-08-10 20:48:55 +00:00
|
|
|
#include "thingdef/thingdef.h"
|
2008-09-14 23:54:38 +00:00
|
|
|
#include "g_level.h"
|
|
|
|
#include "doomstat.h"
|
2008-09-15 14:11:05 +00:00
|
|
|
*/
|
2006-02-24 04:48:15 +00:00
|
|
|
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
|
|
|
|
{
|
2008-08-06 22:59:24 +00:00
|
|
|
DECLARE_CLASS (AProgLevelEnder, AInventory)
|
2006-02-24 04:48:15 +00:00
|
|
|
public:
|
|
|
|
void Tick ();
|
|
|
|
PalEntry GetBlend ();
|
|
|
|
};
|
|
|
|
|
2008-08-06 22:59:24 +00:00
|
|
|
IMPLEMENT_CLASS (AProgLevelEnder)
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// 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 ()
|
|
|
|
{
|
2006-12-21 04:34:43 +00:00
|
|
|
return PalEntry ((BYTE)special1, 0, 0, 0);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_ProgrammerMelee
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerMelee)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
int damage;
|
|
|
|
|
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
A_FaceTarget (self);
|
|
|
|
|
|
|
|
if (!self->CheckMeleeRange ())
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
S_Sound (self, CHAN_WEAPON, "programmer/clank", 1, ATTN_NORM);
|
|
|
|
|
|
|
|
damage = ((pr_prog() % 10) + 1) * 6;
|
2013-01-02 04:39:59 +00:00
|
|
|
int newdam = P_DamageMobj (self->target, self, self, damage, NAME_Melee);
|
|
|
|
P_TraceBleed (newdam > 0 ? newdam : damage, self->target, self);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_SpotLightning
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_SpotLightning)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
AActor *spot;
|
|
|
|
|
|
|
|
if (self->target == NULL)
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
2016-01-19 10:50:07 +00:00
|
|
|
spot = Spawn("SpectralLightningSpot", self->target->X(), self->target->Y(), self->target->floorz, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (spot != NULL)
|
|
|
|
{
|
|
|
|
spot->threshold = 25;
|
|
|
|
spot->target = self;
|
2012-05-13 11:17:27 +00:00
|
|
|
spot->FriendPlayer = 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
spot->tracer = self->target;
|
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_SpawnProgrammerBase
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_SpawnProgrammerBase)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
2016-01-19 12:59:53 +00:00
|
|
|
|
|
|
|
AActor *foo = Spawn("ProgrammerBase", self->PosPlusZ(24*FRACUNIT), ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
if (foo != NULL)
|
|
|
|
{
|
|
|
|
foo->angle = self->angle + ANGLE_180 + (pr_prog.Random2() << 22);
|
2009-06-30 20:57:51 +00:00
|
|
|
foo->velx = FixedMul (foo->Speed, finecosine[foo->angle >> ANGLETOFINESHIFT]);
|
|
|
|
foo->vely = FixedMul (foo->Speed, finesine[foo->angle >> ANGLETOFINESHIFT]);
|
|
|
|
foo->velz = pr_prog() << 9;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_ProgrammerDeath
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
2008-08-10 20:48:55 +00:00
|
|
|
DEFINE_ACTION_FUNCTION(AActor, A_ProgrammerDeath)
|
2006-02-24 04:48:15 +00:00
|
|
|
{
|
2010-02-12 06:04:57 +00:00
|
|
|
PARAM_ACTION_PROLOGUE;
|
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
if (!CheckBossDeath (self))
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < MAXPLAYERS; ++i)
|
|
|
|
{
|
|
|
|
if (playeringame[i] && players[i].health > 0)
|
|
|
|
{
|
|
|
|
players[i].mo->GiveInventoryType (RUNTIME_CLASS(AProgLevelEnder));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2006-04-18 22:15:05 +00:00
|
|
|
// the sky change scripts are now done as special actions in MAPINFO
|
2008-08-10 22:48:37 +00:00
|
|
|
CALL_ACTION(A_BossDeath, self);
|
2010-02-12 06:04:57 +00:00
|
|
|
return 0;
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|