mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-01-18 23:52:02 +00:00
- partial scriptification of the Heresiarch
This commit is contained in:
parent
e01f680b72
commit
f5b3429274
3 changed files with 372 additions and 405 deletions
|
@ -11,23 +11,6 @@
|
||||||
#include "g_level.h"
|
#include "g_level.h"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// Sorcerer stuff
|
|
||||||
//
|
|
||||||
// Sorcerer Variables
|
|
||||||
// specialf1 Angle of ball 1 (all others relative to that)
|
|
||||||
// StopBall which ball to stop at in stop mode (MT_???)
|
|
||||||
// args[0] Defense time
|
|
||||||
// args[1] Number of full rotations since stopping mode
|
|
||||||
// args[2] Target orbit speed for acceleration/deceleration
|
|
||||||
// args[3] Movement mode (see SORC_ macros)
|
|
||||||
// args[4] Current ball orbit speed
|
|
||||||
// Sorcerer Ball Variables
|
|
||||||
// specialf1 Previous angle of ball (for woosh)
|
|
||||||
// special2 Countdown of rapid fire (FX4)
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
#define SORCBALL_INITIAL_SPEED 7
|
#define SORCBALL_INITIAL_SPEED 7
|
||||||
#define SORCBALL_TERMINAL_SPEED 25
|
#define SORCBALL_TERMINAL_SPEED 25
|
||||||
#define SORCBALL_SPEED_ROTATIONS 5
|
#define SORCBALL_SPEED_ROTATIONS 5
|
||||||
|
@ -209,42 +192,7 @@ void ASorcBall1::DoFireSpell ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
DEFINE_FIELD(AHeresiarch, BallAngle);
|
||||||
//
|
|
||||||
// A_SorcSpinBalls
|
|
||||||
//
|
|
||||||
// Spawn spinning balls above head - actor is sorcerer
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcSpinBalls)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AHeresiarch);
|
|
||||||
|
|
||||||
AActor *mo;
|
|
||||||
|
|
||||||
self->SpawnState += 2; // [RH] Don't spawn balls again
|
|
||||||
A_SlowBalls(self);
|
|
||||||
self->args[0] = 0; // Currently no defense
|
|
||||||
self->args[3] = SORC_NORMAL;
|
|
||||||
self->args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed
|
|
||||||
self->BallAngle = 1.;
|
|
||||||
|
|
||||||
DVector3 pos = self->PosPlusZ(-self->Floorclip + self->Height);
|
|
||||||
|
|
||||||
mo = Spawn("SorcBall1", pos, NO_REPLACE);
|
|
||||||
if (mo)
|
|
||||||
{
|
|
||||||
mo->target = self;
|
|
||||||
mo->special2 = SORCFX4_RAPIDFIRE_TIME;
|
|
||||||
}
|
|
||||||
mo = Spawn("SorcBall2", pos, NO_REPLACE);
|
|
||||||
if (mo) mo->target = self;
|
|
||||||
mo = Spawn("SorcBall3", pos, NO_REPLACE);
|
|
||||||
if (mo) mo->target = self;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// A_SorcBallOrbit
|
// A_SorcBallOrbit
|
||||||
|
@ -370,38 +318,6 @@ DEFINE_ACTION_FUNCTION(AActor, A_SorcBallOrbit)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SpeedBalls
|
|
||||||
//
|
|
||||||
// Set balls to speed mode - self is sorcerer
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SpeedBalls)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
self->args[3] = SORC_ACCELERATE; // speed mode
|
|
||||||
self->args[2] = SORCBALL_TERMINAL_SPEED; // target speed
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SlowBalls
|
|
||||||
//
|
|
||||||
// Set balls to slow mode - actor is sorcerer
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
void A_SlowBalls(AActor *self)
|
|
||||||
{
|
|
||||||
self->args[3] = SORC_DECELERATE; // slow mode
|
|
||||||
self->args[2] = SORCBALL_INITIAL_SPEED; // target speed
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
//
|
//
|
||||||
// A_StopBalls
|
// A_StopBalls
|
||||||
|
@ -666,303 +582,3 @@ void A_SorcOffense2(AActor *self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcBossAttack
|
|
||||||
//
|
|
||||||
// Resume ball spinning
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcBossAttack)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
self->args[3] = SORC_ACCELERATE;
|
|
||||||
self->args[2] = SORCBALL_INITIAL_SPEED;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SpawnFizzle
|
|
||||||
//
|
|
||||||
// spell cast magic fizzle
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SpawnFizzle)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
int speed = (int)self->Speed;
|
|
||||||
DAngle rangle;
|
|
||||||
AActor *mo;
|
|
||||||
int ix;
|
|
||||||
|
|
||||||
DVector3 pos = self->Vec3Angle(5., self->Angles.Yaw, -self->Floorclip + self->Height / 2. );
|
|
||||||
for (ix=0; ix<5; ix++)
|
|
||||||
{
|
|
||||||
mo = Spawn("SorcSpark1", pos, ALLOW_REPLACE);
|
|
||||||
if (mo)
|
|
||||||
{
|
|
||||||
rangle = self->Angles.Yaw + (pr_heresiarch() % 5) * (4096 / 360.);
|
|
||||||
mo->Vel.X = (pr_heresiarch() % speed) * rangle.Cos();
|
|
||||||
mo->Vel.Y = (pr_heresiarch() % speed) * rangle.Sin();
|
|
||||||
mo->Vel.Z = 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcFX1Seek
|
|
||||||
//
|
|
||||||
// Yellow spell - offense
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcFX1Seek)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
A_DoBounceCheck (self, "SorcererHeadScream");
|
|
||||||
P_SeekerMissile(self, 2, 6);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcFX2Split
|
|
||||||
//
|
|
||||||
// Blue spell - defense
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// FX2 Variables
|
|
||||||
// specialf1 current angle
|
|
||||||
// special2
|
|
||||||
// args[0] 0 = CW, 1 = CCW
|
|
||||||
// args[1]
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
// Split ball in two
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Split)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
AActor *mo;
|
|
||||||
|
|
||||||
mo = Spawn(self->GetClass(), self->Pos(), NO_REPLACE);
|
|
||||||
if (mo)
|
|
||||||
{
|
|
||||||
mo->target = self->target;
|
|
||||||
mo->args[0] = 0; // CW
|
|
||||||
mo->specialf1 = self->Angles.Yaw.Degrees; // Set angle
|
|
||||||
mo->SetState (mo->FindState("Orbit"));
|
|
||||||
}
|
|
||||||
mo = Spawn(self->GetClass(), self->Pos(), NO_REPLACE);
|
|
||||||
if (mo)
|
|
||||||
{
|
|
||||||
mo->target = self->target;
|
|
||||||
mo->args[0] = 1; // CCW
|
|
||||||
mo->specialf1 = self->Angles.Yaw.Degrees; // Set angle
|
|
||||||
mo->SetState (mo->FindState("Orbit"));
|
|
||||||
}
|
|
||||||
self->Destroy ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcFX2Orbit
|
|
||||||
//
|
|
||||||
// Orbit FX2 about sorcerer
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcFX2Orbit)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
DAngle angle;
|
|
||||||
DVector3 pos;
|
|
||||||
AActor *parent = self->target;
|
|
||||||
|
|
||||||
// [RH] If no parent, then disappear
|
|
||||||
if (parent == NULL)
|
|
||||||
{
|
|
||||||
self->Destroy();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double dist = parent->radius;
|
|
||||||
|
|
||||||
if ((parent->health <= 0) || // Sorcerer is dead
|
|
||||||
(!parent->args[0])) // Time expired
|
|
||||||
{
|
|
||||||
self->SetState (self->FindState(NAME_Death));
|
|
||||||
parent->args[0] = 0;
|
|
||||||
parent->flags2 &= ~MF2_REFLECTIVE;
|
|
||||||
parent->flags2 &= ~MF2_INVULNERABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->args[0] && (parent->args[0]-- <= 0)) // Time expired
|
|
||||||
{
|
|
||||||
self->SetState (self->FindState(NAME_Death));
|
|
||||||
parent->args[0] = 0;
|
|
||||||
parent->flags2 &= ~MF2_REFLECTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move to new position based on angle
|
|
||||||
if (self->args[0]) // Counter clock-wise
|
|
||||||
{
|
|
||||||
self->specialf1 += 10;
|
|
||||||
angle = self->specialf1;
|
|
||||||
pos = parent->Vec3Angle(dist, angle, parent->Floorclip + SORC_DEFENSE_HEIGHT);
|
|
||||||
pos.Z += 15 * angle.Cos();
|
|
||||||
// Spawn trailer
|
|
||||||
Spawn("SorcFX2T1", pos, ALLOW_REPLACE);
|
|
||||||
}
|
|
||||||
else // Clock wise
|
|
||||||
{
|
|
||||||
self->specialf1 -= 10;
|
|
||||||
angle = self->specialf1;
|
|
||||||
pos = parent->Vec3Angle(dist, angle, parent->Floorclip + SORC_DEFENSE_HEIGHT);
|
|
||||||
pos.Z += 20 * angle.Sin();
|
|
||||||
// Spawn trailer
|
|
||||||
Spawn("SorcFX2T1", pos, ALLOW_REPLACE);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->SetOrigin (pos, true);
|
|
||||||
self->floorz = parent->floorz;
|
|
||||||
self->ceilingz = parent->ceilingz;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SpawnBishop
|
|
||||||
//
|
|
||||||
// Green spell - spawn bishops
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SpawnBishop)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
AActor *mo;
|
|
||||||
mo = Spawn("Bishop", self->Pos(), ALLOW_REPLACE);
|
|
||||||
if (mo)
|
|
||||||
{
|
|
||||||
if (!P_TestMobjLocation(mo))
|
|
||||||
{
|
|
||||||
mo->ClearCounters();
|
|
||||||
mo->Destroy ();
|
|
||||||
}
|
|
||||||
else if (self->target != NULL)
|
|
||||||
{ // [RH] Make the new bishops inherit the Heriarch's target
|
|
||||||
mo->CopyFriendliness (self->target, true);
|
|
||||||
mo->master = self->target;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self->Destroy ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcererBishopEntry
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcererBishopEntry)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
Spawn("SorcFX3Explosion", self->Pos(), ALLOW_REPLACE);
|
|
||||||
S_Sound (self, CHAN_VOICE, self->SeeSound, 1, ATTN_NORM);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcFX4Check
|
|
||||||
//
|
|
||||||
// FX4 - rapid fire balls
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcFX4Check)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
if (self->special2-- <= 0)
|
|
||||||
{
|
|
||||||
self->SetState (self->FindState(NAME_Death));
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_SorcBallPop
|
|
||||||
//
|
|
||||||
// Ball death - bounce away in a random direction
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_SorcBallPop)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
S_Sound (self, CHAN_BODY, "SorcererBallPop", 1, ATTN_NONE);
|
|
||||||
self->flags &= ~MF_NOGRAVITY;
|
|
||||||
self->Gravity = 1. / 8;;
|
|
||||||
|
|
||||||
self->Vel.X = ((pr_heresiarch()%10)-5);
|
|
||||||
self->Vel.Y = ((pr_heresiarch()%10)-5);
|
|
||||||
self->Vel.Z = (2+(pr_heresiarch()%3));
|
|
||||||
self->args[4] = BOUNCE_TIME_UNIT; // Bounce time unit
|
|
||||||
self->args[3] = 5; // Bounce time in seconds
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_DoBounceCheck
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
void A_DoBounceCheck (AActor *self, const char *sound)
|
|
||||||
{
|
|
||||||
if (self->args[4]-- <= 0)
|
|
||||||
{
|
|
||||||
if (self->args[3]-- <= 0)
|
|
||||||
{
|
|
||||||
self->SetState (self->FindState(NAME_Death));
|
|
||||||
S_Sound (self, CHAN_BODY, sound, 1, ATTN_NONE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self->args[4] = BOUNCE_TIME_UNIT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
//
|
|
||||||
// A_BounceCheck
|
|
||||||
//
|
|
||||||
//============================================================================
|
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(AActor, A_BounceCheck)
|
|
||||||
{
|
|
||||||
PARAM_SELF_PROLOGUE(AActor);
|
|
||||||
|
|
||||||
A_DoBounceCheck (self, "SorcererBigBallExplode");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
|
@ -262,12 +262,12 @@ extend class Actor
|
||||||
|
|
||||||
if (!isdefault)
|
if (!isdefault)
|
||||||
{
|
{
|
||||||
A_PlaySound(self.AttackSound, CHAN_WEAPON);
|
A_PlaySound(self.AttackSound, CHAN_WEAPON, 1., false, ATTN_NONE);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// compatibility fallback
|
// compatibility fallback
|
||||||
A_PlaySound("brain/spit", CHAN_WEAPON);
|
A_PlaySound("brain/spit", CHAN_WEAPON, 1., false, ATTN_NONE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,52 @@
|
||||||
|
|
||||||
// The Heresiarch him/itself ------------------------------------------------
|
// The Heresiarch him/itself ------------------------------------------------
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// Sorcerer stuff
|
||||||
|
//
|
||||||
|
// Sorcerer Variables
|
||||||
|
// specialf1 Angle of ball 1 (all others relative to that)
|
||||||
|
// StopBall which ball to stop at in stop mode (MT_???)
|
||||||
|
// args[0] Defense time
|
||||||
|
// args[1] Number of full rotations since stopping mode
|
||||||
|
// args[2] Target orbit speed for acceleration/deceleration
|
||||||
|
// args[3] Movement mode (see SORC_ macros)
|
||||||
|
// args[4] Current ball orbit speed
|
||||||
|
// Sorcerer Ball Variables
|
||||||
|
// specialf1 Previous angle of ball (for woosh)
|
||||||
|
// special2 Countdown of rapid fire (FX4)
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
class Heresiarch native
|
class Heresiarch native
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const SORCBALL_INITIAL_SPEED = 7;
|
||||||
|
const SORCBALL_TERMINAL_SPEED = 25;
|
||||||
|
const SORCBALL_SPEED_ROTATIONS = 5;
|
||||||
|
const SORC_DEFENSE_TIME = 255;
|
||||||
|
const SORC_DEFENSE_HEIGHT = 45;
|
||||||
|
const BOUNCE_TIME_UNIT = (35/2);
|
||||||
|
const SORCFX4_RAPIDFIRE_TIME = (6*3); // 3 seconds
|
||||||
|
const SORCFX4_SPREAD_ANGLE = 20;
|
||||||
|
|
||||||
|
enum ESorc
|
||||||
|
{
|
||||||
|
SORC_DECELERATE,
|
||||||
|
SORC_ACCELERATE,
|
||||||
|
SORC_STOPPING,
|
||||||
|
SORC_FIRESPELL,
|
||||||
|
SORC_STOPPED,
|
||||||
|
SORC_NORMAL,
|
||||||
|
SORC_FIRING_SPELL
|
||||||
|
}
|
||||||
|
|
||||||
|
const BALL1_ANGLEOFFSET = 0.;
|
||||||
|
const BALL2_ANGLEOFFSET = 120.;
|
||||||
|
const BALL3_ANGLEOFFSET = 240.;
|
||||||
|
|
||||||
|
native double BallAngle;
|
||||||
|
|
||||||
Default
|
Default
|
||||||
{
|
{
|
||||||
Health 5000;
|
Health 5000;
|
||||||
|
@ -27,11 +71,6 @@ class Heresiarch native
|
||||||
Obituary "$OB_HERESIARCH";
|
Obituary "$OB_HERESIARCH";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SorcSpinBalls();
|
|
||||||
native void A_SpeedBalls();
|
|
||||||
native void A_SorcBossAttack();
|
|
||||||
native void A_SpawnFizzle();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -71,6 +110,105 @@ class Heresiarch native
|
||||||
SORC Z -1 Bright;
|
SORC Z -1 Bright;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcSpinBalls
|
||||||
|
//
|
||||||
|
// Spawn spinning balls above head - actor is sorcerer
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcSpinBalls()
|
||||||
|
{
|
||||||
|
A_SlowBalls();
|
||||||
|
args[0] = 0; // Currently no defense
|
||||||
|
args[3] = SORC_NORMAL;
|
||||||
|
args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed
|
||||||
|
BallAngle = 1.;
|
||||||
|
|
||||||
|
Vector3 ballpos = (pos.xy, -Floorclip + Height);
|
||||||
|
|
||||||
|
Actor mo = Spawn("SorcBall1", pos, NO_REPLACE);
|
||||||
|
if (mo)
|
||||||
|
{
|
||||||
|
mo.target = self;
|
||||||
|
mo.special2 = SORCFX4_RAPIDFIRE_TIME;
|
||||||
|
}
|
||||||
|
mo = Spawn("SorcBall2", pos, NO_REPLACE);
|
||||||
|
if (mo) mo.target = self;
|
||||||
|
mo = Spawn("SorcBall3", pos, NO_REPLACE);
|
||||||
|
if (mo) mo.target = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SpeedBalls
|
||||||
|
//
|
||||||
|
// Set balls to speed mode - self is sorcerer
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SpeedBalls()
|
||||||
|
{
|
||||||
|
args[3] = SORC_ACCELERATE; // speed mode
|
||||||
|
args[2] = SORCBALL_TERMINAL_SPEED; // target speed
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SlowBalls
|
||||||
|
//
|
||||||
|
// Set balls to slow mode - actor is sorcerer
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SlowBalls()
|
||||||
|
{
|
||||||
|
args[3] = SORC_DECELERATE; // slow mode
|
||||||
|
args[2] = SORCBALL_INITIAL_SPEED; // target speed
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcBossAttack
|
||||||
|
//
|
||||||
|
// Resume ball spinning
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcBossAttack()
|
||||||
|
{
|
||||||
|
args[3] = SORC_ACCELERATE;
|
||||||
|
args[2] = SORCBALL_INITIAL_SPEED;
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SpawnFizzle
|
||||||
|
//
|
||||||
|
// spell cast magic fizzle
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SpawnFizzle()
|
||||||
|
{
|
||||||
|
Vector3 pos = Vec3Angle(5., Angle, -Floorclip + Height / 2. );
|
||||||
|
for (int ix=0; ix<5; ix++)
|
||||||
|
{
|
||||||
|
Actor mo = Spawn("SorcSpark1", pos, ALLOW_REPLACE);
|
||||||
|
if (mo)
|
||||||
|
{
|
||||||
|
double rangle = Angle + (random[Heresiarch]() % 5) * (4096 / 360.);
|
||||||
|
mo.Vel.X = (random[Heresiarch]() % speed) * cos(rangle);
|
||||||
|
mo.Vel.Y = (random[Heresiarch]() % speed) * sin(rangle);
|
||||||
|
mo.Vel.Z = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base class for the balls flying around the Heresiarch's head -------------
|
// Base class for the balls flying around the Heresiarch's head -------------
|
||||||
|
@ -94,14 +232,56 @@ class SorcBall native
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SorcBallOrbit();
|
native void A_SorcBallOrbit();
|
||||||
native void A_SorcBallPop();
|
|
||||||
native void A_BounceCheck ();
|
|
||||||
|
|
||||||
void A_SorcBallExplode()
|
void A_SorcBallExplode()
|
||||||
{
|
{
|
||||||
bNOBOUNCESOUND = true;
|
bNoBounceSound = true;
|
||||||
A_Explode(255, 255);
|
A_Explode(255, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcBallPop
|
||||||
|
//
|
||||||
|
// Ball death - bounce away in a random direction
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcBallPop()
|
||||||
|
{
|
||||||
|
A_PlaySound ("SorcererBallPop", CHAN_BODY, 1, false, ATTN_NONE);
|
||||||
|
bNoGravity = false;
|
||||||
|
Gravity = 1. / 8;
|
||||||
|
|
||||||
|
Vel.X = ((random[Heresiarch]()%10)-5);
|
||||||
|
Vel.Y = ((random[Heresiarch]()%10)-5);
|
||||||
|
Vel.Z = (2+(random[Heresiarch]()%3));
|
||||||
|
args[4] = Heresiarch.BOUNCE_TIME_UNIT; // Bounce time unit
|
||||||
|
args[3] = 5; // Bounce time in seconds
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_BounceCheck
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_BounceCheck ()
|
||||||
|
{
|
||||||
|
if (args[4]-- <= 0)
|
||||||
|
{
|
||||||
|
if (args[3]-- <= 0)
|
||||||
|
{
|
||||||
|
SetStateLabel("Death");
|
||||||
|
A_PlaySound ("SorcererBigBallExplode", CHAN_BODY, 1, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args[4] = Heresiarch.BOUNCE_TIME_UNIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// First ball (purple) - fires projectiles ----------------------------------
|
// First ball (purple) - fires projectiles ----------------------------------
|
||||||
|
@ -191,8 +371,6 @@ class SorcFX1 : Actor
|
||||||
DeathSound "SorcererHeadScream";
|
DeathSound "SorcererHeadScream";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SorcFX1Seek();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -204,6 +382,32 @@ class SorcFX1 : Actor
|
||||||
FHFX SS 6 Bright;
|
FHFX SS 6 Bright;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcFX1Seek
|
||||||
|
//
|
||||||
|
// Yellow spell - offense
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcFX1Seek()
|
||||||
|
{
|
||||||
|
if (args[4]-- <= 0)
|
||||||
|
{
|
||||||
|
if (args[3]-- <= 0)
|
||||||
|
{
|
||||||
|
SetStateLabel("Death");
|
||||||
|
A_PlaySound ("SorcererHeadScream", CHAN_BODY, 1, false, ATTN_NONE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args[4] = Heresiarch.BOUNCE_TIME_UNIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
A_SeekerMissile(2, 6);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,9 +425,6 @@ class SorcFX2 : Actor
|
||||||
+NOTELEPORT
|
+NOTELEPORT
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SorcFX2Split();
|
|
||||||
native void A_SorcFX2Orbit ();
|
|
||||||
|
|
||||||
states
|
states
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -237,6 +438,106 @@ class SorcFX2 : Actor
|
||||||
SBS2 A 10;
|
SBS2 A 10;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcFX2Split
|
||||||
|
//
|
||||||
|
// Blue spell - defense
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// FX2 Variables
|
||||||
|
// specialf1 current angle
|
||||||
|
// special2
|
||||||
|
// args[0] 0 = CW, 1 = CCW
|
||||||
|
// args[1]
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
// Split ball in two
|
||||||
|
void A_SorcFX2Split()
|
||||||
|
{
|
||||||
|
Actor mo = Spawn(GetClass(), Pos, NO_REPLACE);
|
||||||
|
if (mo)
|
||||||
|
{
|
||||||
|
mo.target = target;
|
||||||
|
mo.args[0] = 0; // CW
|
||||||
|
mo.specialf1 = Angle; // Set angle
|
||||||
|
mo.SetStateLabel("Orbit");
|
||||||
|
}
|
||||||
|
mo = Spawn(GetClass(), Pos, NO_REPLACE);
|
||||||
|
if (mo)
|
||||||
|
{
|
||||||
|
mo.target = target;
|
||||||
|
mo.args[0] = 1; // CCW
|
||||||
|
mo.specialf1 = Angle; // Set angle
|
||||||
|
mo.SetStateLabel("Orbit");
|
||||||
|
}
|
||||||
|
Destroy ();
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcFX2Orbit
|
||||||
|
//
|
||||||
|
// Orbit FX2 about sorcerer
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcFX2Orbit ()
|
||||||
|
{
|
||||||
|
Actor parent = target;
|
||||||
|
|
||||||
|
// [RH] If no parent, then disappear
|
||||||
|
if (parent == NULL)
|
||||||
|
{
|
||||||
|
Destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
double dist = parent.radius;
|
||||||
|
|
||||||
|
if ((parent.health <= 0) || // Sorcerer is dead
|
||||||
|
(!parent.args[0])) // Time expired
|
||||||
|
{
|
||||||
|
SetStateLabel("Death");
|
||||||
|
parent.args[0] = 0;
|
||||||
|
parent.bReflective = false;
|
||||||
|
parent.bInvulnerable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args[0] && (parent.args[0]-- <= 0)) // Time expired
|
||||||
|
{
|
||||||
|
SetStateLabel("Death");
|
||||||
|
parent.args[0] = 0;
|
||||||
|
parent.bReflective = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector3 posi;
|
||||||
|
// Move to new position based on angle
|
||||||
|
if (args[0]) // Counter clock-wise
|
||||||
|
{
|
||||||
|
specialf1 += 10;
|
||||||
|
angle = specialf1;
|
||||||
|
posi = parent.Vec3Angle(dist, angle, parent.Floorclip + Heresiarch.SORC_DEFENSE_HEIGHT);
|
||||||
|
posi.Z += 15 * cos(angle);
|
||||||
|
// Spawn trailer
|
||||||
|
Spawn("SorcFX2T1", pos, ALLOW_REPLACE);
|
||||||
|
}
|
||||||
|
else // Clock wise
|
||||||
|
{
|
||||||
|
specialf1 -= 10;
|
||||||
|
angle = specialf1;
|
||||||
|
posi = parent.Vec3Angle(dist, angle, parent.Floorclip + Heresiarch.SORC_DEFENSE_HEIGHT);
|
||||||
|
posi.Z += 20 * sin(angle);
|
||||||
|
// Spawn trailer
|
||||||
|
Spawn("SorcFX2T1", pos, ALLOW_REPLACE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetOrigin (posi, true);
|
||||||
|
floorz = parent.floorz;
|
||||||
|
ceilingz = parent.ceilingz;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The translucent trail behind SorcFX2 -------------------------------------
|
// The translucent trail behind SorcFX2 -------------------------------------
|
||||||
|
@ -271,9 +572,6 @@ class SorcFX3 : Actor
|
||||||
SeeSound "SorcererBishopSpawn";
|
SeeSound "SorcererBishopSpawn";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SpawnBishop();
|
|
||||||
native void A_SorcererBishopEntry();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -287,6 +585,45 @@ class SorcFX3 : Actor
|
||||||
BISH G 3 A_SpawnBishop;
|
BISH G 3 A_SpawnBishop;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcererBishopEntry
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcererBishopEntry()
|
||||||
|
{
|
||||||
|
Spawn("SorcFX3Explosion", Pos, ALLOW_REPLACE);
|
||||||
|
A_PlaySound (SeeSound, CHAN_VOICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SpawnBishop
|
||||||
|
//
|
||||||
|
// Green spell - spawn bishops
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SpawnBishop()
|
||||||
|
{
|
||||||
|
Actor mo = Spawn("Bishop", Pos, ALLOW_REPLACE);
|
||||||
|
if (mo)
|
||||||
|
{
|
||||||
|
if (!mo.TestMobjLocation())
|
||||||
|
{
|
||||||
|
mo.ClearCounters();
|
||||||
|
mo.Destroy ();
|
||||||
|
}
|
||||||
|
else if (target != NULL)
|
||||||
|
{ // [RH] Make the new bishops inherit the Heriarch's target
|
||||||
|
mo.CopyFriendliness (target, true);
|
||||||
|
mo.master = target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Destroy ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -326,8 +663,6 @@ class SorcFX4 : Actor
|
||||||
DeathSound "SorcererBallExplode";
|
DeathSound "SorcererBallExplode";
|
||||||
}
|
}
|
||||||
|
|
||||||
native void A_SorcFX4Check();
|
|
||||||
|
|
||||||
States
|
States
|
||||||
{
|
{
|
||||||
Spawn:
|
Spawn:
|
||||||
|
@ -339,6 +674,22 @@ class SorcFX4 : Actor
|
||||||
SBS4 FGH 2 Bright;
|
SBS4 FGH 2 Bright;
|
||||||
Stop;
|
Stop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
//
|
||||||
|
// A_SorcFX4Check
|
||||||
|
//
|
||||||
|
// FX4 - rapid fire balls
|
||||||
|
//
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
void A_SorcFX4Check()
|
||||||
|
{
|
||||||
|
if (special2-- <= 0)
|
||||||
|
{
|
||||||
|
SetStateLabel ("Death");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue