2006-02-24 04:48:15 +00:00
|
|
|
#include "actor.h"
|
|
|
|
#include "gi.h"
|
|
|
|
#include "m_random.h"
|
|
|
|
#include "s_sound.h"
|
|
|
|
#include "d_player.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "p_local.h"
|
|
|
|
#include "p_enemy.h"
|
|
|
|
#include "a_action.h"
|
|
|
|
#include "p_pspr.h"
|
|
|
|
#include "gstrings.h"
|
|
|
|
#include "a_hexenglobal.h"
|
|
|
|
|
|
|
|
#define ZAGSPEED FRACUNIT
|
|
|
|
|
|
|
|
static FRandom pr_lightningready ("LightningReady");
|
|
|
|
static FRandom pr_lightningclip ("LightningClip");
|
|
|
|
static FRandom pr_zap ("LightningZap");
|
|
|
|
static FRandom pr_zapf ("LightningZapF");
|
|
|
|
static FRandom pr_hit ("LightningHit");
|
|
|
|
|
|
|
|
void A_LightningReady (AActor *actor);
|
|
|
|
void A_MLightningAttack (AActor *actor);
|
|
|
|
|
|
|
|
void A_LightningClip (AActor *);
|
|
|
|
void A_LightningZap (AActor *);
|
|
|
|
void A_ZapMimic (AActor *);
|
|
|
|
void A_LastZap (AActor *);
|
|
|
|
void A_LightningRemove (AActor *);
|
|
|
|
void A_FreeTargMobj (AActor *);
|
|
|
|
|
|
|
|
// The Mage's Lightning Arc of Death ----------------------------------------
|
|
|
|
|
|
|
|
class AMWeapLightning : public AMageWeapon
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (AMWeapLightning, AMageWeapon)
|
|
|
|
};
|
|
|
|
|
|
|
|
FState AMWeapLightning::States[] =
|
|
|
|
{
|
|
|
|
#define S_MW_LIGHTNING1 0
|
|
|
|
S_BRIGHT (WMLG, 'A', 4, NULL , &States[S_MW_LIGHTNING1+1]),
|
|
|
|
S_BRIGHT (WMLG, 'B', 4, NULL , &States[S_MW_LIGHTNING1+2]),
|
|
|
|
S_BRIGHT (WMLG, 'C', 4, NULL , &States[S_MW_LIGHTNING1+3]),
|
|
|
|
S_BRIGHT (WMLG, 'D', 4, NULL , &States[S_MW_LIGHTNING1+4]),
|
|
|
|
S_BRIGHT (WMLG, 'E', 4, NULL , &States[S_MW_LIGHTNING1+5]),
|
|
|
|
S_BRIGHT (WMLG, 'F', 4, NULL , &States[S_MW_LIGHTNING1+6]),
|
|
|
|
S_BRIGHT (WMLG, 'G', 4, NULL , &States[S_MW_LIGHTNING1+7]),
|
|
|
|
S_BRIGHT (WMLG, 'H', 4, NULL , &States[S_MW_LIGHTNING1]),
|
|
|
|
|
|
|
|
#define S_MLIGHTNINGREADY (S_MW_LIGHTNING1+8)
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+1]),
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+2]),
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+3]),
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+4]),
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+5]),
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_LightningReady , &States[S_MLIGHTNINGREADY+6]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+7]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+8]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+9]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+10]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+11]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+12]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+13]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+14]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+15]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+16]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+17]),
|
|
|
|
S_BRIGHT (MLNG, 'C', 1, A_LightningReady , &States[S_MLIGHTNINGREADY+18]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+19]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+20]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+21]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+22]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY+23]),
|
|
|
|
S_BRIGHT (MLNG, 'B', 1, A_WeaponReady , &States[S_MLIGHTNINGREADY]),
|
|
|
|
|
|
|
|
#define S_MLIGHTNINGDOWN (S_MLIGHTNINGREADY+24)
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_Lower , &States[S_MLIGHTNINGDOWN]),
|
|
|
|
|
|
|
|
#define S_MLIGHTNINGUP (S_MLIGHTNINGDOWN+1)
|
|
|
|
S_BRIGHT (MLNG, 'A', 1, A_Raise , &States[S_MLIGHTNINGUP]),
|
|
|
|
|
|
|
|
#define S_MLIGHTNINGATK (S_MLIGHTNINGUP+1)
|
|
|
|
S_BRIGHT (MLNG, 'D', 3, NULL , &States[S_MLIGHTNINGATK+1]),
|
|
|
|
S_BRIGHT (MLNG, 'E', 3, NULL , &States[S_MLIGHTNINGATK+2]),
|
|
|
|
S_BRIGHT (MLNG, 'F', 4, A_MLightningAttack , &States[S_MLIGHTNINGATK+3]),
|
|
|
|
S_BRIGHT (MLNG, 'G', 4, NULL , &States[S_MLIGHTNINGATK+4]),
|
|
|
|
S_BRIGHT (MLNG, 'H', 3, NULL , &States[S_MLIGHTNINGATK+5]),
|
|
|
|
S_BRIGHT (MLNG, 'I', 3, NULL , &States[S_MLIGHTNINGATK+6]),
|
|
|
|
S_BRIGHT2 (MLNG, 'I', 6, NULL , &States[S_MLIGHTNINGATK+7], 0, 199),
|
|
|
|
S_BRIGHT2 (MLNG, 'C', 2, NULL , &States[S_MLIGHTNINGATK+8], 0, 55),
|
|
|
|
S_BRIGHT2 (MLNG, 'B', 2, NULL , &States[S_MLIGHTNINGATK+9], 0, 50),
|
|
|
|
S_BRIGHT2 (MLNG, 'B', 2, NULL , &States[S_MLIGHTNINGATK+10], 0, 45),
|
|
|
|
S_BRIGHT2 (MLNG, 'B', 2, NULL , &States[S_MLIGHTNINGREADY], 0, 40),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (AMWeapLightning, Hexen, 8040, 0)
|
|
|
|
PROP_Flags (MF_SPECIAL|MF_NOGRAVITY)
|
|
|
|
PROP_SpawnState (S_MW_LIGHTNING1)
|
|
|
|
|
|
|
|
PROP_Weapon_SelectionOrder (1100)
|
|
|
|
PROP_Weapon_AmmoUse1 (5)
|
|
|
|
PROP_Weapon_AmmoGive1 (25)
|
|
|
|
PROP_Weapon_UpState (S_MLIGHTNINGUP)
|
|
|
|
PROP_Weapon_DownState (S_MLIGHTNINGDOWN)
|
|
|
|
PROP_Weapon_ReadyState (S_MLIGHTNINGREADY)
|
|
|
|
PROP_Weapon_AtkState (S_MLIGHTNINGATK)
|
|
|
|
PROP_Weapon_HoldAtkState (S_MLIGHTNINGATK)
|
|
|
|
PROP_Weapon_Kickback (0)
|
|
|
|
PROP_Weapon_YAdjust (20)
|
|
|
|
PROP_Weapon_MoveCombatDist (23000000)
|
|
|
|
PROP_Weapon_AmmoType1 ("Mana2")
|
|
|
|
PROP_Weapon_ProjectileType ("LightningFloor")
|
2006-06-17 20:29:41 +00:00
|
|
|
PROP_Inventory_PickupMessage("$TXT_WEAPON_M3")
|
2006-02-24 04:48:15 +00:00
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
// Lightning ----------------------------------------------------------------
|
|
|
|
|
|
|
|
IMPLEMENT_ABSTRACT_ACTOR (ALightning)
|
|
|
|
|
|
|
|
int ALightning::SpecialMissileHit (AActor *thing)
|
|
|
|
{
|
|
|
|
if (thing->flags&MF_SHOOTABLE && thing != target)
|
|
|
|
{
|
|
|
|
if (thing->Mass != INT_MAX)
|
|
|
|
{
|
|
|
|
thing->momx += momx>>4;
|
|
|
|
thing->momy += momy>>4;
|
|
|
|
}
|
|
|
|
if ((!thing->player && !(thing->flags2&MF2_BOSS))
|
|
|
|
|| !(level.time&1))
|
|
|
|
{
|
|
|
|
if (thing->IsKindOf(RUNTIME_CLASS(ACentaur)))
|
|
|
|
{ // Lightning does more damage to centaurs
|
|
|
|
P_DamageMobj(thing, this, target, 9, MOD_ELECTRIC);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
P_DamageMobj(thing, this, target, 3, MOD_ELECTRIC);
|
|
|
|
}
|
|
|
|
if (!(S_IsActorPlayingSomething (this, CHAN_WEAPON)))
|
|
|
|
{
|
|
|
|
S_Sound (this, CHAN_WEAPON, "MageLightningZap", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
if (thing->flags3&MF3_ISMONSTER && pr_hit() < 64)
|
|
|
|
{
|
|
|
|
thing->Howl ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
health--;
|
|
|
|
if (health <= 0 || thing->health <= 0)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (flags3 & MF3_FLOORHUGGER)
|
|
|
|
{
|
|
|
|
if (lastenemy && ! lastenemy->tracer)
|
|
|
|
{
|
|
|
|
lastenemy->tracer = thing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!tracer)
|
|
|
|
{
|
|
|
|
tracer = thing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 1; // lightning zaps through all sprites
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ceiling Lightning --------------------------------------------------------
|
|
|
|
|
|
|
|
class ALightningCeiling : public ALightning
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (ALightningCeiling, ALightning)
|
|
|
|
};
|
|
|
|
|
|
|
|
FState ALightningCeiling::States[] =
|
|
|
|
{
|
|
|
|
#define S_LIGHTNING_CEILING1 0
|
|
|
|
S_BRIGHT (MLFX, 'A', 2, A_LightningZap , &States[S_LIGHTNING_CEILING1+1]),
|
|
|
|
S_BRIGHT (MLFX, 'B', 2, A_LightningClip , &States[S_LIGHTNING_CEILING1+2]),
|
|
|
|
S_BRIGHT (MLFX, 'C', 2, A_LightningClip , &States[S_LIGHTNING_CEILING1+3]),
|
|
|
|
S_BRIGHT (MLFX, 'D', 2, A_LightningClip , &States[S_LIGHTNING_CEILING1]),
|
|
|
|
|
|
|
|
#define S_LIGHTNING_C_X1 (S_LIGHTNING_CEILING1+4)
|
|
|
|
S_BRIGHT (MLF2, 'A', 2, A_LightningRemove , &States[S_LIGHTNING_C_X1+1]),
|
|
|
|
S_BRIGHT (MLF2, 'B', 3, NULL , &States[S_LIGHTNING_C_X1+2]),
|
|
|
|
S_BRIGHT (MLF2, 'C', 3, NULL , &States[S_LIGHTNING_C_X1+3]),
|
|
|
|
S_BRIGHT (MLF2, 'D', 3, NULL , &States[S_LIGHTNING_C_X1+4]),
|
|
|
|
S_BRIGHT (MLF2, 'E', 3, NULL , &States[S_LIGHTNING_C_X1+5]),
|
|
|
|
S_BRIGHT (MLF2, 'K', 3, NULL , &States[S_LIGHTNING_C_X1+6]),
|
|
|
|
S_BRIGHT (MLF2, 'L', 3, NULL , &States[S_LIGHTNING_C_X1+7]),
|
|
|
|
S_BRIGHT (MLF2, 'M', 3, NULL , &States[S_LIGHTNING_C_X1+8]),
|
|
|
|
S_NORMAL (ACLO, 'E', 35, NULL , &States[S_LIGHTNING_C_X1+9]),
|
|
|
|
S_BRIGHT (MLF2, 'N', 3, NULL , &States[S_LIGHTNING_C_X1+10]),
|
|
|
|
S_BRIGHT (MLF2, 'O', 3, NULL , &States[S_LIGHTNING_C_X1+11]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 4, NULL , &States[S_LIGHTNING_C_X1+12]),
|
|
|
|
S_BRIGHT (MLF2, 'Q', 3, NULL , &States[S_LIGHTNING_C_X1+13]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_C_X1+14]),
|
|
|
|
S_BRIGHT (MLF2, 'Q', 4, NULL , &States[S_LIGHTNING_C_X1+15]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_C_X1+16]),
|
|
|
|
S_BRIGHT (MLF2, 'O', 3, NULL , &States[S_LIGHTNING_C_X1+17]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_C_X1+18]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 1, A_HideThing , &States[S_LIGHTNING_C_X1+19]),
|
|
|
|
S_NORMAL (ACLO, 'E', 1050, A_FreeTargMobj , NULL),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (ALightningCeiling, Hexen, -1, 0)
|
|
|
|
PROP_SpawnHealth (144)
|
|
|
|
PROP_SpeedFixed (25)
|
|
|
|
PROP_RadiusFixed (16)
|
|
|
|
PROP_HeightFixed (40)
|
|
|
|
PROP_Damage (8)
|
|
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
|
|
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
|
|
|
|
PROP_Flags3 (MF3_CEILINGHUGGER)
|
|
|
|
PROP_RenderStyle (STYLE_Add)
|
|
|
|
|
|
|
|
PROP_SpawnState (S_LIGHTNING_CEILING1)
|
|
|
|
PROP_DeathState (S_LIGHTNING_C_X1)
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
// Floor Lightning ----------------------------------------------------------
|
|
|
|
|
|
|
|
class ALightningFloor : public ALightning
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (ALightningFloor, ALightning)
|
|
|
|
};
|
|
|
|
|
|
|
|
FState ALightningFloor::States[] =
|
|
|
|
{
|
|
|
|
#define S_LIGHTNING_FLOOR1 0
|
|
|
|
S_BRIGHT (MLFX, 'E', 2, A_LightningZap , &States[S_LIGHTNING_FLOOR1+1]),
|
|
|
|
S_BRIGHT (MLFX, 'F', 2, A_LightningClip , &States[S_LIGHTNING_FLOOR1+2]),
|
|
|
|
S_BRIGHT (MLFX, 'G', 2, A_LightningClip , &States[S_LIGHTNING_FLOOR1+3]),
|
|
|
|
S_BRIGHT (MLFX, 'H', 2, A_LightningClip , &States[S_LIGHTNING_FLOOR1]),
|
|
|
|
|
|
|
|
#define S_LIGHTNING_F_X1 (S_LIGHTNING_FLOOR1+4)
|
|
|
|
S_BRIGHT (MLF2, 'F', 2, A_LightningRemove , &States[S_LIGHTNING_F_X1+1]),
|
|
|
|
S_BRIGHT (MLF2, 'G', 3, NULL , &States[S_LIGHTNING_F_X1+2]),
|
|
|
|
S_BRIGHT (MLF2, 'H', 3, NULL , &States[S_LIGHTNING_F_X1+3]),
|
|
|
|
S_BRIGHT (MLF2, 'I', 3, NULL , &States[S_LIGHTNING_F_X1+4]),
|
|
|
|
S_BRIGHT (MLF2, 'J', 3, NULL , &States[S_LIGHTNING_F_X1+5]),
|
|
|
|
S_BRIGHT (MLF2, 'K', 3, NULL , &States[S_LIGHTNING_F_X1+6]),
|
|
|
|
S_BRIGHT (MLF2, 'L', 3, NULL , &States[S_LIGHTNING_F_X1+7]),
|
|
|
|
S_BRIGHT (MLF2, 'M', 3, NULL , &States[S_LIGHTNING_F_X1+8]),
|
|
|
|
S_NORMAL (ACLO, 'E', 20, NULL , &States[S_LIGHTNING_F_X1+9]),
|
|
|
|
S_BRIGHT (MLF2, 'N', 3, NULL , &States[S_LIGHTNING_F_X1+10]),
|
|
|
|
S_BRIGHT (MLF2, 'O', 3, NULL , &States[S_LIGHTNING_F_X1+11]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 4, NULL , &States[S_LIGHTNING_F_X1+12]),
|
|
|
|
S_BRIGHT (MLF2, 'Q', 3, NULL , &States[S_LIGHTNING_F_X1+13]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_F_X1+14]),
|
|
|
|
S_BRIGHT (MLF2, 'Q', 4, A_LastZap , &States[S_LIGHTNING_F_X1+15]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_F_X1+16]),
|
|
|
|
S_BRIGHT (MLF2, 'O', 3, NULL , &States[S_LIGHTNING_F_X1+17]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 3, NULL , &States[S_LIGHTNING_F_X1+18]),
|
|
|
|
S_BRIGHT (MLF2, 'P', 1, A_HideThing , &ALightningCeiling::States[S_LIGHTNING_C_X1+19]),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (ALightningFloor, Hexen, -1, 0)
|
|
|
|
PROP_SpawnHealth (144)
|
|
|
|
PROP_SpeedFixed (25)
|
|
|
|
PROP_RadiusFixed (16)
|
|
|
|
PROP_HeightFixed (40)
|
|
|
|
PROP_Damage (8)
|
|
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
|
|
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_IMPACT|MF2_PCROSS)
|
|
|
|
PROP_Flags3 (MF3_FLOORHUGGER)
|
|
|
|
PROP_RenderStyle (STYLE_Add)
|
|
|
|
|
|
|
|
PROP_SpawnState (S_LIGHTNING_FLOOR1)
|
|
|
|
PROP_DeathState (S_LIGHTNING_F_X1)
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
// Lightning Zap ------------------------------------------------------------
|
|
|
|
|
|
|
|
class ALightningZap : public AActor
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (ALightningZap, AActor)
|
|
|
|
public:
|
|
|
|
int SpecialMissileHit (AActor *thing);
|
|
|
|
};
|
|
|
|
|
|
|
|
FState ALightningZap::States[] =
|
|
|
|
{
|
|
|
|
#define S_LIGHTNING_ZAP1 0
|
|
|
|
S_BRIGHT (MLFX, 'I', 2, A_ZapMimic , &States[S_LIGHTNING_ZAP1+1]),
|
|
|
|
S_BRIGHT (MLFX, 'J', 2, A_ZapMimic , &States[S_LIGHTNING_ZAP1+2]),
|
|
|
|
S_BRIGHT (MLFX, 'K', 2, A_ZapMimic , &States[S_LIGHTNING_ZAP1+3]),
|
|
|
|
S_BRIGHT (MLFX, 'L', 2, A_ZapMimic , &States[S_LIGHTNING_ZAP1+4]),
|
|
|
|
S_BRIGHT (MLFX, 'M', 2, A_ZapMimic , &States[S_LIGHTNING_ZAP1]),
|
|
|
|
|
|
|
|
#define S_LIGHTNING_ZAP_X1 (S_LIGHTNING_ZAP1+5)
|
|
|
|
S_BRIGHT (MLFX, 'N', 2, NULL , &States[S_LIGHTNING_ZAP_X1+1]),
|
|
|
|
S_BRIGHT (MLFX, 'O', 2, NULL , &States[S_LIGHTNING_ZAP_X1+2]),
|
|
|
|
S_BRIGHT (MLFX, 'P', 2, NULL , &States[S_LIGHTNING_ZAP_X1+3]),
|
|
|
|
S_BRIGHT (MLFX, 'Q', 2, NULL , &States[S_LIGHTNING_ZAP_X1+4]),
|
|
|
|
S_BRIGHT (MLFX, 'R', 2, NULL , &States[S_LIGHTNING_ZAP_X1+5]),
|
|
|
|
S_BRIGHT (MLFX, 'S', 2, NULL , &States[S_LIGHTNING_ZAP_X1+6]),
|
|
|
|
S_BRIGHT (MLFX, 'T', 2, NULL , &States[S_LIGHTNING_ZAP_X1+7]),
|
|
|
|
S_BRIGHT (MLFX, 'U', 2, NULL , NULL),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (ALightningZap, Hexen, -1, 0)
|
|
|
|
PROP_RadiusFixed (15)
|
|
|
|
PROP_HeightFixed (35)
|
|
|
|
PROP_Damage (2)
|
|
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
|
|
|
PROP_RenderStyle (STYLE_Add)
|
|
|
|
|
|
|
|
PROP_SpawnState (S_LIGHTNING_ZAP1)
|
|
|
|
PROP_DeathState (S_LIGHTNING_ZAP_X1+7)
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
int ALightningZap::SpecialMissileHit (AActor *thing)
|
|
|
|
{
|
|
|
|
AActor *lmo;
|
|
|
|
|
|
|
|
if (thing->flags&MF_SHOOTABLE && thing != target)
|
|
|
|
{
|
|
|
|
lmo = lastenemy;
|
|
|
|
if (lmo)
|
|
|
|
{
|
|
|
|
if (lmo->flags3 & MF3_FLOORHUGGER)
|
|
|
|
{
|
|
|
|
if (lmo->lastenemy && !lmo->lastenemy->tracer)
|
|
|
|
{
|
|
|
|
lmo->lastenemy->tracer = thing;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (!lmo->tracer)
|
|
|
|
{
|
|
|
|
lmo->tracer = thing;
|
|
|
|
}
|
|
|
|
if (!(level.time&3))
|
|
|
|
{
|
|
|
|
lmo->health--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LightningReady
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LightningReady (AActor *actor)
|
|
|
|
{
|
|
|
|
A_WeaponReady (actor);
|
|
|
|
if (pr_lightningready() < 160)
|
|
|
|
{
|
|
|
|
S_Sound (actor, CHAN_WEAPON, "MageLightningReady", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LightningClip
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LightningClip (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *cMo;
|
|
|
|
AActor *target = NULL;
|
|
|
|
int zigZag;
|
|
|
|
|
|
|
|
if (actor->flags3 & MF3_FLOORHUGGER)
|
|
|
|
{
|
|
|
|
if (actor->lastenemy == NULL)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
actor->z = actor->floorz;
|
|
|
|
target = actor->lastenemy->tracer;
|
|
|
|
}
|
|
|
|
else if (actor->flags3 & MF3_CEILINGHUGGER)
|
|
|
|
{
|
|
|
|
actor->z = actor->ceilingz-actor->height;
|
|
|
|
target = actor->tracer;
|
|
|
|
}
|
|
|
|
if (actor->flags3 & MF3_FLOORHUGGER)
|
|
|
|
{ // floor lightning zig-zags, and forces the ceiling lightning to mimic
|
|
|
|
cMo = actor->lastenemy;
|
|
|
|
zigZag = pr_lightningclip();
|
|
|
|
if((zigZag > 128 && actor->special1 < 2) || actor->special1 < -2)
|
|
|
|
{
|
|
|
|
P_ThrustMobj(actor, actor->angle+ANG90, ZAGSPEED);
|
|
|
|
if(cMo)
|
|
|
|
{
|
|
|
|
P_ThrustMobj(cMo, actor->angle+ANG90, ZAGSPEED);
|
|
|
|
}
|
|
|
|
actor->special1++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
P_ThrustMobj(actor, actor->angle-ANG90, ZAGSPEED);
|
|
|
|
if(cMo)
|
|
|
|
{
|
|
|
|
P_ThrustMobj(cMo, cMo->angle-ANG90, ZAGSPEED);
|
|
|
|
}
|
|
|
|
actor->special1--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(target)
|
|
|
|
{
|
|
|
|
if(target->health <= 0)
|
|
|
|
{
|
|
|
|
P_ExplodeMissile(actor, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actor->angle = R_PointToAngle2(actor->x, actor->y, target->x, target->y);
|
|
|
|
actor->momx = 0;
|
|
|
|
actor->momy = 0;
|
|
|
|
P_ThrustMobj (actor, actor->angle, actor->Speed>>1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LightningZap
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LightningZap (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
fixed_t deltaZ;
|
|
|
|
|
|
|
|
A_LightningClip(actor);
|
|
|
|
|
|
|
|
actor->health -= 8;
|
|
|
|
if (actor->health <= 0)
|
|
|
|
{
|
|
|
|
actor->SetState (actor->DeathState);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (actor->flags3 & MF3_FLOORHUGGER)
|
|
|
|
{
|
|
|
|
deltaZ = 10*FRACUNIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
deltaZ = -10*FRACUNIT;
|
|
|
|
}
|
|
|
|
mo = Spawn<ALightningZap> (actor->x+((pr_zap()-128)*actor->radius/256),
|
|
|
|
actor->y+((pr_zap()-128)*actor->radius/256),
|
|
|
|
actor->z+deltaZ);
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->lastenemy = actor;
|
|
|
|
mo->momx = actor->momx;
|
|
|
|
mo->momy = actor->momy;
|
|
|
|
mo->target = actor->target;
|
|
|
|
if (actor->flags3 & MF3_FLOORHUGGER)
|
|
|
|
{
|
|
|
|
mo->momz = 20*FRACUNIT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
mo->momz = -20*FRACUNIT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((actor->flags3 & MF3_FLOORHUGGER) && pr_zapf() < 160)
|
|
|
|
{
|
|
|
|
S_Sound (actor, CHAN_BODY, "MageLightningContinuous", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_MLightningAttack2
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_MLightningAttack2 (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *fmo, *cmo;
|
|
|
|
|
|
|
|
fmo = P_SpawnPlayerMissile (actor, RUNTIME_CLASS(ALightningFloor));
|
|
|
|
cmo = P_SpawnPlayerMissile (actor, RUNTIME_CLASS(ALightningCeiling));
|
|
|
|
if (fmo)
|
|
|
|
{
|
|
|
|
fmo->special1 = 0;
|
|
|
|
fmo->lastenemy = cmo;
|
|
|
|
A_LightningZap (fmo);
|
|
|
|
}
|
|
|
|
if (cmo)
|
|
|
|
{
|
|
|
|
cmo->tracer = NULL;
|
|
|
|
cmo->lastenemy = fmo;
|
|
|
|
A_LightningZap (cmo);
|
|
|
|
}
|
|
|
|
S_Sound (actor, CHAN_BODY, "MageLightningFire", 1, ATTN_NORM);
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_MLightningAttack
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_MLightningAttack (AActor *actor)
|
|
|
|
{
|
|
|
|
A_MLightningAttack2(actor);
|
|
|
|
if (actor->player != NULL)
|
|
|
|
{
|
|
|
|
AWeapon *weapon = actor->player->ReadyWeapon;
|
|
|
|
if (weapon != NULL)
|
|
|
|
{
|
|
|
|
weapon->DepleteAmmo (weapon->bAltFire);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_ZapMimic
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_ZapMimic (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
mo = actor->lastenemy;
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
if (mo->state >= mo->DeathState)
|
|
|
|
{
|
|
|
|
P_ExplodeMissile (actor, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
actor->momx = mo->momx;
|
|
|
|
actor->momy = mo->momy;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LastZap
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LastZap (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
mo = Spawn<ALightningZap> (actor->x, actor->y, actor->z);
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->SetState (&ALightningZap::States[S_LIGHTNING_ZAP_X1]);
|
|
|
|
mo->momz = 40*FRACUNIT;
|
|
|
|
mo->damage = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_LightningRemove
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_LightningRemove (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
mo = actor->lastenemy;
|
|
|
|
if (mo)
|
|
|
|
{
|
|
|
|
mo->lastenemy = NULL;
|
|
|
|
P_ExplodeMissile (mo, NULL);
|
|
|
|
}
|
|
|
|
}
|