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"
|
|
|
|
|
|
|
|
static FRandom pr_smoke ("MWandSmoke");
|
|
|
|
|
|
|
|
void A_MWandAttack (AActor *actor);
|
|
|
|
|
|
|
|
// The Mage's Wand ----------------------------------------------------------
|
|
|
|
|
|
|
|
class AMWeapWand : public AMageWeapon
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (AMWeapWand, AMageWeapon)
|
|
|
|
};
|
|
|
|
|
|
|
|
FState AMWeapWand::States[] =
|
|
|
|
{
|
|
|
|
#define S_MWANDREADY 0
|
|
|
|
S_NORMAL (MWND, 'A', 1, A_WeaponReady , &States[S_MWANDREADY]),
|
|
|
|
|
|
|
|
#define S_MWANDDOWN (S_MWANDREADY+1)
|
|
|
|
S_NORMAL (MWND, 'A', 1, A_Lower , &States[S_MWANDDOWN]),
|
|
|
|
|
|
|
|
#define S_MWANDUP (S_MWANDDOWN+1)
|
|
|
|
S_NORMAL (MWND, 'A', 1, A_Raise , &States[S_MWANDUP]),
|
|
|
|
|
|
|
|
#define S_MWANDATK (S_MWANDUP+1)
|
|
|
|
S_NORMAL (MWND, 'A', 6, NULL , &States[S_MWANDATK+1]),
|
|
|
|
S_BRIGHT2 (MWND, 'B', 6, A_MWandAttack , &States[S_MWANDATK+2], 0, 48),
|
|
|
|
S_NORMAL2 (MWND, 'A', 3, NULL , &States[S_MWANDATK+3], 0, 40),
|
|
|
|
S_NORMAL2 (MWND, 'A', 3, A_ReFire , &States[S_MWANDREADY], 0, 36),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (AMWeapWand, Hexen, -1, 0)
|
|
|
|
PROP_Weapon_SelectionOrder (3600)
|
|
|
|
PROP_Weapon_UpState (S_MWANDUP)
|
|
|
|
PROP_Weapon_DownState (S_MWANDDOWN)
|
|
|
|
PROP_Weapon_ReadyState (S_MWANDREADY)
|
|
|
|
PROP_Weapon_AtkState (S_MWANDATK)
|
|
|
|
PROP_Weapon_Kickback (0)
|
|
|
|
PROP_Weapon_YAdjust (9)
|
|
|
|
PROP_Weapon_MoveCombatDist (25000000)
|
|
|
|
PROP_Weapon_ProjectileType ("MageWandMissile")
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
// Wand Smoke ---------------------------------------------------------------
|
|
|
|
|
|
|
|
class AMageWandSmoke : public AActor
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (AMageWandSmoke, AActor)
|
|
|
|
};
|
|
|
|
|
|
|
|
FState AMageWandSmoke::States[] =
|
|
|
|
{
|
|
|
|
S_NORMAL (MWND, 'C', 4, NULL , &States[1]),
|
|
|
|
S_NORMAL (MWND, 'D', 4, NULL , &States[2]),
|
|
|
|
S_NORMAL (MWND, 'C', 4, NULL , &States[3]),
|
|
|
|
S_NORMAL (MWND, 'D', 4, NULL , NULL),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (AMageWandSmoke, Hexen, -1, 0)
|
|
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_SHADOW)
|
|
|
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_CANNOTPUSH|MF2_NODMGTHRUST)
|
|
|
|
PROP_SpawnState (0)
|
|
|
|
PROP_RenderStyle (STYLE_Translucent)
|
|
|
|
PROP_Alpha (HX_SHADOW)
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
// Wand Missile -------------------------------------------------------------
|
|
|
|
|
|
|
|
class AMageWandMissile : public AActor
|
|
|
|
{
|
|
|
|
DECLARE_ACTOR (AMageWandMissile, AActor)
|
|
|
|
public:
|
|
|
|
void Tick ();
|
|
|
|
};
|
|
|
|
|
|
|
|
FState AMageWandMissile::States[] =
|
|
|
|
{
|
|
|
|
#define S_MWAND_MISSILE 0
|
|
|
|
S_BRIGHT (MWND, 'C', 4, NULL , &States[S_MWAND_MISSILE+1]),
|
|
|
|
S_BRIGHT (MWND, 'D', 4, NULL , &States[S_MWAND_MISSILE]),
|
|
|
|
|
|
|
|
#define S_MWANDPUFF (S_MWAND_MISSILE+2)
|
|
|
|
S_BRIGHT (MWND, 'E', 4, NULL , &States[S_MWANDPUFF+1]),
|
|
|
|
S_BRIGHT (MWND, 'F', 3, NULL , &States[S_MWANDPUFF+2]),
|
|
|
|
S_BRIGHT (MWND, 'G', 4, NULL , &States[S_MWANDPUFF+3]),
|
|
|
|
S_BRIGHT (MWND, 'H', 3, NULL , &States[S_MWANDPUFF+4]),
|
|
|
|
S_BRIGHT (MWND, 'I', 4, NULL , NULL),
|
|
|
|
};
|
|
|
|
|
|
|
|
IMPLEMENT_ACTOR (AMageWandMissile, Hexen, -1, 0)
|
|
|
|
PROP_SpeedFixed (184)
|
|
|
|
PROP_RadiusFixed (12)
|
|
|
|
PROP_HeightFixed (8)
|
|
|
|
PROP_Damage (2)
|
|
|
|
PROP_Flags (MF_NOBLOCKMAP|MF_NOGRAVITY|MF_DROPOFF|MF_MISSILE)
|
|
|
|
PROP_Flags2 (MF2_NOTELEPORT|MF2_RIP|MF2_CANNOTPUSH|MF2_NODMGTHRUST|MF2_IMPACT|MF2_PCROSS)
|
|
|
|
|
|
|
|
PROP_SpawnState (S_MWAND_MISSILE)
|
|
|
|
PROP_DeathState (S_MWANDPUFF)
|
|
|
|
END_DEFAULTS
|
|
|
|
|
|
|
|
void AMageWandMissile::Tick ()
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
fixed_t xfrac;
|
|
|
|
fixed_t yfrac;
|
|
|
|
fixed_t zfrac;
|
|
|
|
fixed_t hitz;
|
|
|
|
bool changexy;
|
|
|
|
|
|
|
|
PrevX = x;
|
|
|
|
PrevY = y;
|
|
|
|
PrevZ = z;
|
|
|
|
|
|
|
|
// [RH] Ripping is a little different than it was in Hexen
|
2008-04-10 14:38:43 +00:00
|
|
|
FCheckPosition tm(!!(flags2 & MF2_RIP));
|
2006-02-24 04:48:15 +00:00
|
|
|
|
|
|
|
// Handle movement
|
|
|
|
if (momx || momy || (z != floorz) || momz)
|
|
|
|
{
|
|
|
|
xfrac = momx>>3;
|
|
|
|
yfrac = momy>>3;
|
|
|
|
zfrac = momz>>3;
|
|
|
|
changexy = xfrac || yfrac;
|
|
|
|
for (i = 0; i < 8; i++)
|
|
|
|
{
|
|
|
|
if (changexy)
|
|
|
|
{
|
2008-04-10 14:38:43 +00:00
|
|
|
tm.LastRipped = NULL; // [RH] Do rip damage each step, like Hexen
|
|
|
|
if (!P_TryMove (this, x+xfrac,y+yfrac, true, false, tm))
|
2006-02-24 04:48:15 +00:00
|
|
|
{ // Blocked move
|
2006-10-22 10:32:41 +00:00
|
|
|
P_ExplodeMissile (this, BlockingLine, BlockingMobj);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
z += zfrac;
|
|
|
|
if (z <= floorz)
|
|
|
|
{ // Hit the floor
|
|
|
|
z = floorz;
|
|
|
|
P_HitFloor (this);
|
2006-10-22 10:32:41 +00:00
|
|
|
P_ExplodeMissile (this, NULL, NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (z+height > ceilingz)
|
|
|
|
{ // Hit the ceiling
|
|
|
|
z = ceilingz-height;
|
2006-10-22 10:32:41 +00:00
|
|
|
P_ExplodeMissile (this, NULL, NULL);
|
2006-02-24 04:48:15 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (changexy)
|
|
|
|
{
|
|
|
|
//if (pr_smoke() < 128) // [RH] I think it looks better if it's consistant
|
|
|
|
{
|
|
|
|
hitz = z-8*FRACUNIT;
|
|
|
|
if (hitz < floorz)
|
|
|
|
{
|
|
|
|
hitz = floorz;
|
|
|
|
}
|
2006-07-16 09:10:45 +00:00
|
|
|
Spawn<AMageWandSmoke> (x, y, hitz, ALLOW_REPLACE);
|
2006-02-24 04:48:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-04-10 14:38:43 +00:00
|
|
|
|
2006-02-24 04:48:15 +00:00
|
|
|
// Advance the state
|
|
|
|
if (tics != -1)
|
|
|
|
{
|
|
|
|
tics--;
|
|
|
|
while (!tics)
|
|
|
|
{
|
|
|
|
if (!SetState (state->GetNextState()))
|
|
|
|
{ // actor was removed
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//============================================================================
|
|
|
|
//
|
|
|
|
// A_MWandAttack
|
|
|
|
//
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
void A_MWandAttack (AActor *actor)
|
|
|
|
{
|
|
|
|
AActor *mo;
|
|
|
|
|
|
|
|
mo = P_SpawnPlayerMissile (actor, RUNTIME_CLASS(AMageWandMissile));
|
|
|
|
S_Sound (actor, CHAN_WEAPON, "MageWandFire", 1, ATTN_NORM);
|
|
|
|
}
|