- scriptified the Phoenix Rod, completing the Heretic weapons.

This commit is contained in:
Christoph Oelckers 2016-11-25 18:13:08 +01:00
parent 53ff7f0c73
commit 4f370ba181
10 changed files with 372 additions and 473 deletions

View file

@ -858,7 +858,6 @@ set( NOT_COMPILED_SOURCE_FILES
sc_man_scanner.h
sc_man_scanner.re
g_heretic/a_hereticartifacts.cpp
g_heretic/a_hereticweaps.cpp
g_hexen/a_blastradius.cpp
g_hexen/a_boostarmor.cpp
g_hexen/a_clericflame.cpp

View file

@ -20,4 +20,3 @@
// Include all the other Heretic stuff here to reduce compile time
#include "a_hereticartifacts.cpp"
#include "a_hereticweaps.cpp"

View file

@ -1,285 +0,0 @@
/*
#include "templates.h"
#include "actor.h"
#include "info.h"
#include "s_sound.h"
#include "m_random.h"
#include "a_pickups.h"
#include "d_player.h"
#include "p_pspr.h"
#include "p_local.h"
#include "gstrings.h"
#include "gi.h"
#include "r_data/r_translate.h"
#include "vm.h"
#include "doomstat.h"
*/
static FRandom pr_boltspark ("BoltSpark");
static FRandom pr_macerespawn ("MaceRespawn");
static FRandom pr_maceatk ("FireMacePL1");
static FRandom pr_bfx1 ("BlasterFX1");
static FRandom pr_ripd ("RipperD");
static FRandom pr_fb1 ("FireBlasterPL1");
static FRandom pr_bfx1t ("BlasterFX1Tick");
static FRandom pr_rp ("RainPillar");
static FRandom pr_fsr1 ("FireSkullRodPL1");
static FRandom pr_storm ("SkullRodStorm");
static FRandom pr_impact ("RainImpact");
static FRandom pr_pfx1 ("PhoenixFX1");
static FRandom pr_pfx2 ("PhoenixFX2");
static FRandom pr_fp2 ("FirePhoenixPL2");
#define FLAME_THROWER_TICS (10*TICRATE)
void P_DSparilTeleport (AActor *actor);
#define USE_BLSR_AMMO_1 1
#define USE_BLSR_AMMO_2 5
#define USE_SKRD_AMMO_1 1
#define USE_SKRD_AMMO_2 5
#define USE_PHRD_AMMO_1 1
#define USE_PHRD_AMMO_2 1
#define USE_MACE_AMMO_1 1
#define USE_MACE_AMMO_2 5
extern bool P_AutoUseChaosDevice (player_t *player);
// --- Phoenix Rod ----------------------------------------------------------
class APhoenixRod : public AWeapon
{
DECLARE_CLASS (APhoenixRod, AWeapon)
public:
void Serialize(FSerializer &arc)
{
Super::Serialize (arc);
arc("flamecount", FlameCount);
}
int FlameCount; // for flamethrower duration
};
class APhoenixRodPowered : public APhoenixRod
{
DECLARE_CLASS (APhoenixRodPowered, APhoenixRod)
public:
void EndPowerup ();
};
IMPLEMENT_CLASS(APhoenixRod, false, false)
IMPLEMENT_CLASS(APhoenixRodPowered, false, false)
void APhoenixRodPowered::EndPowerup ()
{
DepleteAmmo (bAltFire);
Owner->player->refire = 0;
S_StopSound (Owner, CHAN_WEAPON);
Owner->player->ReadyWeapon = SisterWeapon;
P_SetPsprite(Owner->player, PSP_WEAPON, SisterWeapon->GetReadyState());
}
// Phoenix FX 2 -------------------------------------------------------------
class APhoenixFX2 : public AActor
{
DECLARE_CLASS (APhoenixFX2, AActor)
public:
int DoSpecialDamage (AActor *target, int damage, FName damagetype);
};
IMPLEMENT_CLASS(APhoenixFX2, false, false)
int APhoenixFX2::DoSpecialDamage (AActor *target, int damage, FName damagetype)
{
if (target->player && pr_pfx2 () < 128)
{ // Freeze player for a bit
target->reactiontime += 4;
}
return damage;
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL1
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL1)
{
PARAM_ACTION_PROLOGUE(AActor);
player_t *player;
if (NULL == (player = self->player))
{
return 0;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
P_SpawnPlayerMissile (self, PClass::FindActor("PhoenixFX1"));
self->Thrust(self->Angles.Yaw + 180, 4);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_PhoenixPuff
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff)
{
PARAM_SELF_PROLOGUE(AActor);
AActor *puff;
DAngle ang;
//[RH] Heretic never sets the target for seeking
//P_SeekerMissile (self, 5, 10);
puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
ang = self->Angles.Yaw + 90;
puff->Vel = DVector3(ang.ToVector(1.3), 0);
puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
ang = self->Angles.Yaw - 90;
puff->Vel = DVector3(ang.ToVector(1.3), 0);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_InitPhoenixPL2
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_InitPhoenixPL2)
{
PARAM_ACTION_PROLOGUE(AActor);
if (self->player != NULL)
{
APhoenixRod *flamethrower = static_cast<APhoenixRod *> (self->player->ReadyWeapon);
if (flamethrower != NULL)
{
flamethrower->FlameCount = FLAME_THROWER_TICS;
}
}
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL2
//
// Flame thrower effect.
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FirePhoenixPL2)
{
PARAM_ACTION_PROLOGUE(AActor);
AActor *mo;
double slope;
FSoundID soundid;
player_t *player;
APhoenixRod *flamethrower;
if (nullptr == (player = self->player))
{
return 0;
}
soundid = "weapons/phoenixpowshoot";
flamethrower = static_cast<APhoenixRod *> (player->ReadyWeapon);
if (flamethrower == nullptr || --flamethrower->FlameCount == 0)
{ // Out of flame
P_SetPsprite(player, PSP_WEAPON, flamethrower->FindState("Powerdown"));
player->refire = 0;
S_StopSound (self, CHAN_WEAPON);
return 0;
}
slope = -self->Angles.Pitch.TanClamped();
double xo = pr_fp2.Random2() / 128.;
double yo = pr_fp2.Random2() / 128.;
DVector3 pos = self->Vec3Offset(xo, yo, 26 + slope - self->Floorclip);
slope += 0.1;
mo = Spawn("PhoenixFX2", pos, ALLOW_REPLACE);
mo->target = self;
mo->Angles.Yaw = self->Angles.Yaw;
mo->VelFromAngle();
mo->Vel += self->Vel.XY();
mo->Vel.Z = mo->Speed * slope;
if (!player->refire || !S_IsActorPlayingSomething (self, CHAN_WEAPON, -1))
{
S_Sound (self, CHAN_WEAPON|CHAN_LOOP, soundid, 1, ATTN_NORM);
}
P_CheckMissileSpawn (mo, self->radius);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_ShutdownPhoenixPL2
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_ShutdownPhoenixPL2)
{
PARAM_ACTION_PROLOGUE(AActor);
player_t *player;
if (NULL == (player = self->player))
{
return 0;
}
S_StopSound (self, CHAN_WEAPON);
AWeapon *weapon = player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FlameEnd
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FlameEnd)
{
PARAM_SELF_PROLOGUE(AActor);
self->Vel.Z += 1.5;
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FloatPuff
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FloatPuff)
{
PARAM_SELF_PROLOGUE(AActor);
self->Vel.Z += 1.8;
return 0;
}

View file

@ -1185,7 +1185,7 @@ void APowerWeaponLevel2::EndEffect ()
if (player->ReadyWeapon != NULL &&
player->ReadyWeapon->WeaponFlags & WIF_POWERED_UP)
{
player->ReadyWeapon->EndPowerup ();
player->ReadyWeapon->CallEndPowerup ();
}
if (player->PendingWeapon != NULL && player->PendingWeapon != WP_NOCHANGE &&
player->PendingWeapon->WeaponFlags & WIF_POWERED_UP &&

View file

@ -342,6 +342,7 @@ public:
virtual void PostMorphWeapon ();
virtual void EndPowerup ();
void CallEndPowerup();
enum
{

View file

@ -18,6 +18,7 @@
#include "d_net.h"
#include "serializer.h"
#include "thingdef.h"
#include "virtual.h"
#define BONUSADD 6
@ -789,6 +790,26 @@ void AWeapon::EndPowerup ()
}
}
DEFINE_ACTION_FUNCTION(AWeapon, EndPowerup)
{
PARAM_SELF_PROLOGUE(AWeapon);
self->EndPowerup();
return 0;
}
void AWeapon::CallEndPowerup()
{
IFVIRTUAL(AWeapon, EndPowerup)
{
// Without the type cast this picks the 'void *' assignment...
VMValue params[1] = { (DObject*)this };
VMFrameStack stack;
stack.Call(func, params, 1, nullptr, 0, nullptr);
}
else EndPowerup();
}
//===========================================================================
//
// AWeapon :: GetUpState

View file

@ -85,7 +85,6 @@ zscript/heretic/hereticartifacts.txt
zscript/heretic/heretickeys.txt
zscript/heretic/hereticdecorations.txt
zscript/heretic/hereticmisc.txt
zscript/heretic/hereticweaps.txt
zscript/heretic/mummy.txt
zscript/heretic/clink.txt
zscript/heretic/beast.txt
@ -103,6 +102,7 @@ zscript/heretic/weapongauntlets.txt
zscript/heretic/weaponmace.txt
zscript/heretic/weaponblaster.txt
zscript/heretic/weaponskullrod.txt
zscript/heretic/weaponphoenix.txt
zscript/hexen/baseweapons.txt
zscript/hexen/korax.txt

View file

@ -1,184 +0,0 @@
class HereticWeapon : Weapon
{
Default
{
Weapon.Kickback 150;
}
}
// Phoenix Rod --------------------------------------------------------------
class PhoenixRod : Weapon native
{
Default
{
+WEAPON.NOAUTOFIRE
Weapon.SelectionOrder 2600;
Weapon.Kickback 150;
Weapon.YAdjust 15;
Weapon.AmmoUse 1;
Weapon.AmmoGive 2;
Weapon.AmmoType "PhoenixRodAmmo";
Weapon.Sisterweapon "PhoenixRodPowered";
Inventory.PickupMessage "$TXT_WPNPHOENIXROD";
Tag "$TAG_PHOENIXROD";
}
action native void A_FirePhoenixPL1();
States
{
Spawn:
WPHX A -1;
Stop;
Ready:
PHNX A 1 A_WeaponReady;
Loop;
Deselect:
PHNX A 1 A_Lower;
Loop;
Select:
PHNX A 1 A_Raise;
Loop;
Fire:
PHNX B 5;
PHNX C 7 A_FirePhoenixPL1;
PHNX DB 4;
PHNX B 0 A_ReFire;
Goto Ready;
}
}
class PhoenixRodPowered : PhoenixRod native
{
Default
{
+WEAPON.POWERED_UP
+WEAPON.MELEEWEAPON
Weapon.SisterWeapon "PhoenixRod";
Weapon.AmmoGive 0;
Tag "$TAG_PHOENIXRODP";
}
action native void A_InitPhoenixPL2();
action native void A_FirePhoenixPL2();
action native void A_ShutdownPhoenixPL2();
States
{
Fire:
PHNX B 3 A_InitPhoenixPL2;
Hold:
PHNX C 1 A_FirePhoenixPL2;
PHNX B 4 A_ReFire;
Powerdown:
PHNX B 4 A_ShutdownPhoenixPL2;
Goto Ready;
}
}
// Phoenix FX 1 -------------------------------------------------------------
class PhoenixFX1 : Actor
{
Default
{
Radius 11;
Height 8;
Speed 20;
Damage 20;
DamageType "Fire";
Projectile;
+THRUGHOST
+SPECIALFIREDAMAGE
SeeSound "weapons/phoenixshoot";
DeathSound "weapons/phoenixhit";
Obituary "$OB_MPPHOENIXROD";
}
native void A_PhoenixPuff();
States
{
Spawn:
FX04 A 4 BRIGHT A_PhoenixPuff;
Loop;
Death:
FX08 A 6 BRIGHT A_Explode;
FX08 BC 5 BRIGHT;
FX08 DEFGH 4 BRIGHT;
Stop;
}
override int DoSpecialDamage (Actor target, int damage, Name damagetype)
{
Sorcerer2 s2 = Sorcerer2(target);
if (s2 != null && random[HornRodFX2]() < 96)
{ // D'Sparil teleports away
s2.DSparilTeleport ();
return -1;
}
return damage;
}
}
// Phoenix puff -------------------------------------------------------------
class PhoenixPuff : Actor
{
Default
{
+NOBLOCKMAP
+NOGRAVITY
+NOTELEPORT
+CANNOTPUSH
RenderStyle "Translucent";
Alpha 0.4;
}
States
{
Spawn:
FX04 BCDEF 4;
Stop;
}
}
// Phoenix FX 2 -------------------------------------------------------------
class PhoenixFX2 : Actor native
{
Default
{
Radius 6;
Height 8;
Speed 10;
Damage 2;
DamageType "Fire";
Projectile;
RenderStyle "Add";
Obituary "$OB_MPPPHOENIXROD";
}
native void A_FlameEnd();
native void A_FloatPuff();
States
{
Spawn:
FX09 ABABA 2 BRIGHT;
FX09 B 2 BRIGHT A_FlameEnd;
FX09 CDEF 2 BRIGHT;
Stop;
Death:
FX09 G 3 BRIGHT;
FX09 H 3 BRIGHT A_FloatPuff;
FX09 I 4 BRIGHT;
FX09 JK 5 BRIGHT;
Stop;
}
}

View file

@ -0,0 +1,347 @@
class HereticWeapon : Weapon
{
Default
{
Weapon.Kickback 150;
}
}
// Phoenix Rod --------------------------------------------------------------
class PhoenixRod : Weapon
{
Default
{
+WEAPON.NOAUTOFIRE
Weapon.SelectionOrder 2600;
Weapon.Kickback 150;
Weapon.YAdjust 15;
Weapon.AmmoUse 1;
Weapon.AmmoGive 2;
Weapon.AmmoType "PhoenixRodAmmo";
Weapon.Sisterweapon "PhoenixRodPowered";
Inventory.PickupMessage "$TXT_WPNPHOENIXROD";
Tag "$TAG_PHOENIXROD";
}
States
{
Spawn:
WPHX A -1;
Stop;
Ready:
PHNX A 1 A_WeaponReady;
Loop;
Deselect:
PHNX A 1 A_Lower;
Loop;
Select:
PHNX A 1 A_Raise;
Loop;
Fire:
PHNX B 5;
PHNX C 7 A_FirePhoenixPL1;
PHNX DB 4;
PHNX B 0 A_ReFire;
Goto Ready;
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL1
//
//----------------------------------------------------------------------------
action void A_FirePhoenixPL1()
{
if (player == null)
{
return;
}
Weapon weapon = player.ReadyWeapon;
if (weapon != null)
{
if (!weapon.DepleteAmmo (weapon.bAltFire))
return;
}
SpawnPlayerMissile ("PhoenixFX1");
Thrust(4, angle + 180);
}
}
class PhoenixRodPowered : PhoenixRod
{
const FLAME_THROWER_TICS = (10*TICRATE);
private int FlameCount; // for flamethrower duration
Default
{
+WEAPON.POWERED_UP
+WEAPON.MELEEWEAPON
Weapon.SisterWeapon "PhoenixRod";
Weapon.AmmoGive 0;
Tag "$TAG_PHOENIXRODP";
}
States
{
Fire:
PHNX B 3 A_InitPhoenixPL2;
Hold:
PHNX C 1 A_FirePhoenixPL2;
PHNX B 4 A_ReFire;
Powerdown:
PHNX B 4 A_ShutdownPhoenixPL2;
Goto Ready;
}
override void EndPowerup ()
{
DepleteAmmo (bAltFire);
Owner.player.refire = 0;
Owner.A_StopSound (CHAN_WEAPON);
Owner.player.ReadyWeapon = SisterWeapon;
Owner.player.SetPsprite(PSP_WEAPON, SisterWeapon.GetReadyState());
}
//----------------------------------------------------------------------------
//
// PROC A_InitPhoenixPL2
//
//----------------------------------------------------------------------------
action void A_InitPhoenixPL2()
{
if (player != null)
{
PhoenixRodPowered flamethrower = PhoenixRodPowered(player.ReadyWeapon);
if (flamethrower != null)
{
flamethrower.FlameCount = FLAME_THROWER_TICS;
}
}
}
//----------------------------------------------------------------------------
//
// PROC A_FirePhoenixPL2
//
// Flame thrower effect.
//
//----------------------------------------------------------------------------
action void A_FirePhoenixPL2()
{
if (player == null)
{
return;
}
PhoenixRodPowered flamethrower = PhoenixRodPowered(player.ReadyWeapon);
if (flamethrower == null || --flamethrower.FlameCount == 0)
{ // Out of flame
player.SetPsprite(PSP_WEAPON, flamethrower.FindState("Powerdown"));
player.refire = 0;
A_StopSound (CHAN_WEAPON);
return;
}
double slope = -clamp(tan(pitch), -5, 5);
double xo = Random2[FirePhoenixPL2]() / 128.;
double yo = Random2[FirePhoenixPL2]() / 128.;
Vector3 spawnpos = Vec3Offset(xo, yo, 26 + slope - Floorclip);
slope += 0.1;
Actor mo = Spawn("PhoenixFX2", spawnpos, ALLOW_REPLACE);
mo.target = self;
mo.Angle = Angle;
mo.VelFromAngle();
mo.Vel.XY += Vel.XY;
mo.Vel.Z = mo.Speed * slope;
if (!player.refire)
{
A_PlaySound("weapons/phoenixpowshoot", CHAN_WEAPON, 1, true);
}
mo.CheckMissileSpawn (radius);
}
//----------------------------------------------------------------------------
//
// PROC A_ShutdownPhoenixPL2
//
//----------------------------------------------------------------------------
action void A_ShutdownPhoenixPL2()
{
if (player == null)
{
return;
}
A_StopSound (CHAN_WEAPON);
Weapon weapon = player.ReadyWeapon;
if (weapon != null)
{
weapon.DepleteAmmo (weapon.bAltFire);
}
}
}
// Phoenix FX 1 -------------------------------------------------------------
class PhoenixFX1 : Actor
{
Default
{
Radius 11;
Height 8;
Speed 20;
Damage 20;
DamageType "Fire";
Projectile;
+THRUGHOST
+SPECIALFIREDAMAGE
SeeSound "weapons/phoenixshoot";
DeathSound "weapons/phoenixhit";
Obituary "$OB_MPPHOENIXROD";
}
States
{
Spawn:
FX04 A 4 BRIGHT A_PhoenixPuff;
Loop;
Death:
FX08 A 6 BRIGHT A_Explode;
FX08 BC 5 BRIGHT;
FX08 DEFGH 4 BRIGHT;
Stop;
}
override int DoSpecialDamage (Actor target, int damage, Name damagetype)
{
Sorcerer2 s2 = Sorcerer2(target);
if (s2 != null && random[HornRodFX2]() < 96)
{ // D'Sparil teleports away
s2.DSparilTeleport ();
return -1;
}
return damage;
}
//----------------------------------------------------------------------------
//
// PROC A_PhoenixPuff
//
//----------------------------------------------------------------------------
void A_PhoenixPuff()
{
//[RH] Heretic never sets the target for seeking
//P_SeekerMissile (self, 5, 10);
Actor puff = Spawn("PhoenixPuff", Pos, ALLOW_REPLACE);
puff.Vel.XY = AngleToVector(Angle + 90, 1.3);
puff = Spawn("PhoenixPuff", Pos, ALLOW_REPLACE);
puff.Vel.XY = AngleToVector(Angle - 90, 1.3);
}
}
// Phoenix puff -------------------------------------------------------------
class PhoenixPuff : Actor
{
Default
{
+NOBLOCKMAP
+NOGRAVITY
+NOTELEPORT
+CANNOTPUSH
RenderStyle "Translucent";
Alpha 0.4;
}
States
{
Spawn:
FX04 BCDEF 4;
Stop;
}
}
// Phoenix FX 2 -------------------------------------------------------------
class PhoenixFX2 : Actor
{
Default
{
Radius 6;
Height 8;
Speed 10;
Damage 2;
DamageType "Fire";
Projectile;
RenderStyle "Add";
Obituary "$OB_MPPPHOENIXROD";
}
States
{
Spawn:
FX09 ABABA 2 BRIGHT;
FX09 B 2 BRIGHT A_FlameEnd;
FX09 CDEF 2 BRIGHT;
Stop;
Death:
FX09 G 3 BRIGHT;
FX09 H 3 BRIGHT A_FloatPuff;
FX09 I 4 BRIGHT;
FX09 JK 5 BRIGHT;
Stop;
}
int DoSpecialDamage (Actor target, int damage, Name damagetype)
{
if (target.player && Random[PhoenixFX2]() < 128)
{ // Freeze player for a bit
target.reactiontime += 4;
}
return damage;
}
//----------------------------------------------------------------------------
//
// PROC A_FlameEnd
//
//----------------------------------------------------------------------------
void A_FlameEnd()
{
Vel.Z += 1.5;
}
//----------------------------------------------------------------------------
//
// PROC A_FloatPuff
//
//----------------------------------------------------------------------------
void A_FloatPuff()
{
Vel.Z += 1.8;
}
}

View file

@ -569,6 +569,7 @@ class Weapon : StateProvider native
}
native bool DepleteAmmo(bool altFire, bool checkEnough = true, int ammouse = -1);
native virtual void EndPowerup();
virtual State GetReadyState ()
{