- scriptified Heretic's staff and wand.

This commit is contained in:
Christoph Oelckers 2016-11-24 10:39:16 +01:00
parent 3e890d182b
commit 2ece9b6172
6 changed files with 393 additions and 428 deletions

View File

@ -15,10 +15,6 @@
#include "doomstat.h"
*/
static FRandom pr_sap ("StaffAtkPL1");
static FRandom pr_sap2 ("StaffAtkPL2");
static FRandom pr_fgw ("FireWandPL1");
static FRandom pr_fgw2 ("FireWandPL2");
static FRandom pr_boltspark ("BoltSpark");
static FRandom pr_macerespawn ("MaceRespawn");
static FRandom pr_maceatk ("FireMacePL1");
@ -50,134 +46,6 @@ void P_DSparilTeleport (AActor *actor);
extern bool P_AutoUseChaosDevice (player_t *player);
// --- Staff ----------------------------------------------------------------
//----------------------------------------------------------------------------
//
// PROC A_StaffAttackPL1
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_StaffAttack)
{
PARAM_ACTION_PROLOGUE(AActor);
DAngle angle;
DAngle slope;
player_t *player;
FTranslatedLineTarget t;
if (NULL == (player = self->player))
{
return 0;
}
PARAM_INT (damage);
PARAM_CLASS (puff, AActor);
AWeapon *weapon = player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
if (puff == NULL)
{
puff = PClass::FindActor(NAME_BulletPuff); // just to be sure
}
angle = self->Angles.Yaw + pr_sap.Random2() * (5.625 / 256);
slope = P_AimLineAttack (self, angle, MELEERANGE);
P_LineAttack (self, angle, MELEERANGE, slope, damage, NAME_Melee, puff, true, &t);
if (t.linetarget)
{
//S_StartSound(player->mo, sfx_stfhit);
// turn to face target
self->Angles.Yaw = t.angleFromSource;
}
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL1
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL1)
{
PARAM_ACTION_PROLOGUE(AActor);
DAngle angle;
int damage;
player_t *player;
if (NULL == (player = self->player))
{
return 0;
}
AWeapon *weapon = player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo(weapon->bAltFire))
return 0;
}
DAngle pitch = P_BulletSlope(self);
damage = 7 + (pr_fgw() & 7);
angle = self->Angles.Yaw;
if (player->refire)
{
angle += pr_fgw.Random2() * (5.625 / 256);
}
P_LineAttack(self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "GoldWandPuff1");
S_Sound(self, CHAN_WEAPON, "weapons/wandhit", 1, ATTN_NORM);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL2
//
//----------------------------------------------------------------------------
DEFINE_ACTION_FUNCTION(AActor, A_FireGoldWandPL2)
{
PARAM_ACTION_PROLOGUE(AActor);
int i;
DAngle angle;
int damage;
double vz;
player_t *player;
if (NULL == (player = self->player))
{
return 0;
}
AWeapon *weapon = player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return 0;
}
DAngle pitch = P_BulletSlope(self);
vz = -GetDefaultByName("GoldWandFX2")->Speed * pitch.TanClamped();
P_SpawnMissileAngle(self, PClass::FindActor("GoldWandFX2"), self->Angles.Yaw - (45. / 8), vz);
P_SpawnMissileAngle(self, PClass::FindActor("GoldWandFX2"), self->Angles.Yaw + (45. / 8), vz);
angle = self->Angles.Yaw - (45. / 8);
for(i = 0; i < 5; i++)
{
damage = 1+(pr_fgw2()&7);
P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "GoldWandPuff2");
angle += ((45. / 8) * 2) / 4;
}
S_Sound (self, CHAN_WEAPON, "weapons/wandhit", 1, ATTN_NORM);
return 0;
}
//----------------------------------------------------------------------------
//
// PROC A_FireCrossbowPL1
@ -323,20 +191,20 @@ DEFINE_ACTION_FUNCTION(AActor, A_GauntletAttack)
S_Sound (self, CHAN_AUTO, "weapons/gauntletshit", 1, ATTN_NORM);
}
// turn to face target
DAngle angle = t.angleFromSource;
DAngle anglediff = deltaangle(self->Angles.Yaw, angle);
DAngle ang = t.angleFromSource;
DAngle anglediff = deltaangle(self->Angles.Yaw, ang);
if (anglediff < 0.0)
{
if (anglediff < -4.5)
self->Angles.Yaw = angle + 90.0 / 21;
self->Angles.Yaw = ang + 90.0 / 21;
else
self->Angles.Yaw -= 4.5;
}
else
{
if (anglediff > 4.5)
self->Angles.Yaw = angle - 90.0 / 21;
self->Angles.Yaw = ang - 90.0 / 21;
else
self->Angles.Yaw += 4.5;
}
@ -477,9 +345,9 @@ DEFINE_ACTION_FUNCTION(AActor, A_MacePL1Check)
// [RH] Avoid some precision loss by scaling the velocity directly
#if 0
// This is the original code, for reference.
a.ngle_t angle = self->angle>>ANGLETOF.INESHIFT;
self->velx = F.ixedMul(7*F.RACUNIT, f.inecosine[angle]);
self->vely = F.ixedMul(7*F.RACUNIT, f.inesine[angle]);
a.ngle_t ang = self->ang>>ANGLETOF.INESHIFT;
self->velx = F.ixedMul(7*F.RACUNIT, f.inecosine[ang]);
self->vely = F.ixedMul(7*F.RACUNIT, f.inesine[ang]);
#else
double velscale = 7 / self->Vel.XY().Length();
self->Vel.X *= velscale;
@ -621,7 +489,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
int i;
AActor *target;
DAngle angle = 0.;
DAngle ang = 0.;
bool newAngle;
FTranslatedLineTarget t;
@ -648,29 +516,29 @@ DEFINE_ACTION_FUNCTION(AActor, A_DeathBallImpact)
}
else
{ // Seek
angle = self->AngleTo(target);
ang = self->AngleTo(target);
newAngle = true;
}
}
else
{ // Find new target
angle = 0.;
ang = 0.;
for (i = 0; i < 16; i++)
{
P_AimLineAttack (self, angle, 640., &t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target);
P_AimLineAttack (self, ang, 640., &t, 0., ALF_NOFRIENDS|ALF_PORTALRESTRICT, NULL, self->target);
if (t.linetarget && self->target != t.linetarget)
{
self->tracer = t.linetarget;
angle = t.angleFromSource;
ang = t.angleFromSource;
newAngle = true;
break;
}
angle += 22.5;
ang += 22.5;
}
}
if (newAngle)
{
self->Angles.Yaw = angle;
self->Angles.Yaw = ang;
self->VelFromAngle();
}
self->SetState (self->SpawnState);
@ -762,7 +630,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1)
{
PARAM_ACTION_PROLOGUE(AActor);
DAngle angle;
DAngle ang;
int damage;
player_t *player;
@ -779,12 +647,12 @@ DEFINE_ACTION_FUNCTION(AActor, A_FireBlasterPL1)
}
DAngle pitch = P_BulletSlope(self);
damage = pr_fb1.HitDice (4);
angle = self->Angles.Yaw;
ang = self->Angles.Yaw;
if (player->refire)
{
angle += pr_fb1.Random2() * (5.625 / 256);
ang += pr_fb1.Random2() * (5.625 / 256);
}
P_LineAttack (self, angle, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "BlasterPuff");
P_LineAttack (self, ang, PLAYERMISSILERANGE, pitch, damage, NAME_Hitscan, "BlasterPuff");
S_Sound (self, CHAN_WEAPON, "weapons/blastershoot", 1, ATTN_NORM);
return 0;
}
@ -800,15 +668,15 @@ DEFINE_ACTION_FUNCTION(AActor, A_SpawnRippers)
PARAM_SELF_PROLOGUE(AActor);
unsigned int i;
DAngle angle;
DAngle ang;
AActor *ripper;
for(i = 0; i < 8; i++)
{
ripper = Spawn<ARipper> (self->Pos(), ALLOW_REPLACE);
angle = i*45.;
ang = i*45.;
ripper->target = self->target;
ripper->Angles.Yaw = angle;
ripper->Angles.Yaw = ang;
ripper->VelFromAngle();
P_CheckMissileSpawn (ripper, self->radius);
}
@ -1207,17 +1075,17 @@ DEFINE_ACTION_FUNCTION(AActor, A_PhoenixPuff)
PARAM_SELF_PROLOGUE(AActor);
AActor *puff;
DAngle angle;
DAngle ang;
//[RH] Heretic never sets the target for seeking
//P_SeekerMissile (self, 5, 10);
puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
angle = self->Angles.Yaw + 90;
puff->Vel = DVector3(angle.ToVector(1.3), 0);
ang = self->Angles.Yaw + 90;
puff->Vel = DVector3(ang.ToVector(1.3), 0);
puff = Spawn("PhoenixPuff", self->Pos(), ALLOW_REPLACE);
angle = self->Angles.Yaw - 90;
puff->Vel = DVector3(angle.ToVector(1.3), 0);
ang = self->Angles.Yaw - 90;
puff->Vel = DVector3(ang.ToVector(1.3), 0);
return 0;
}

View File

@ -49,6 +49,7 @@ xx(TK_Until, "'until'")
xx(TK_While, "'while'")
xx(TK_Bool, "'bool'")
xx(TK_Float, "'float'")
xx(TK_Float32, "'float32'")
xx(TK_Double, "'double'")
xx(TK_Char, "'char'")
xx(TK_Byte, "'byte'")

View File

@ -95,6 +95,8 @@ zscript/heretic/wizard.txt
zscript/heretic/ironlich.txt
zscript/heretic/dsparil.txt
zscript/heretic/chicken.txt
zscript/heretic/weaponstaff.txt
zscript/heretic/weaponwand.txt
zscript/hexen/baseweapons.txt
zscript/hexen/korax.txt

View File

@ -8,276 +8,6 @@ class HereticWeapon : Weapon
}
// Staff --------------------------------------------------------------------
class Staff : HereticWeapon
{
Default
{
Weapon.SelectionOrder 3800;
+THRUGHOST
+WEAPON.WIMPY_WEAPON
+WEAPON.MELEEWEAPON
Weapon.sisterweapon "StaffPowered";
Obituary "$OB_MPSTAFF";
Tag "$TAG_STAFF";
}
action native void A_StaffAttack (int damage, class<Actor> puff);
States
{
Ready:
STFF A 1 A_WeaponReady;
Loop;
Deselect:
STFF A 1 A_Lower;
Loop;
Select:
STFF A 1 A_Raise;
Loop;
Fire:
STFF B 6;
STFF C 8 A_StaffAttack(random[StaffAttack](5, 20), "StaffPuff");
STFF B 8 A_ReFire;
Goto Ready;
}
}
class StaffPowered : Staff
{
Default
{
Weapon.sisterweapon "Staff";
Weapon.ReadySound "weapons/staffcrackle";
+WEAPON.POWERED_UP
+WEAPON.READYSNDHALF
+WEAPON.STAFF2_KICKBACK
Obituary "$OB_MPPSTAFF";
Tag "$TAG_STAFFP";
}
States
{
Ready:
STFF DEF 4 A_WeaponReady;
Loop;
Deselect:
STFF D 1 A_Lower;
Loop;
Select:
STFF D 1 A_Raise;
Loop;
Fire:
STFF G 6;
STFF H 8 A_StaffAttack(random[StaffAttack](18, 81), "StaffPuff2");
STFF G 8 A_ReFire;
Goto Ready;
}
}
// Staff puff ---------------------------------------------------------------
class StaffPuff : Actor
{
Default
{
RenderStyle "Translucent";
Alpha 0.4;
VSpeed 1;
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
AttackSound "weapons/staffhit";
}
States
{
Spawn:
PUF3 A 4 BRIGHT;
PUF3 BCD 4;
Stop;
}
}
// Staff puff 2 -------------------------------------------------------------
class StaffPuff2 : Actor
{
Default
{
RenderStyle "Add";
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
AttackSound "weapons/staffpowerhit";
}
States
{
Spawn:
PUF4 ABCDEF 4 BRIGHT;
Stop;
}
}
// Gold wand ----------------------------------------------------------------
class GoldWand : HereticWeapon
{
Default
{
+BLOODSPLATTER
Weapon.SelectionOrder 2000;
Weapon.AmmoGive 25;
Weapon.AmmoUse 1;
Weapon.AmmoType "GoldWandAmmo";
Weapon.SisterWeapon "GoldWandPowered";
Weapon.YAdjust 5;
Inventory.PickupMessage "$TXT_WPNGOLDWAND";
Obituary "$OB_MPGOLDWAND";
Tag "$TAG_GOLDWAND";
}
action native void A_FireGoldWandPL1 ();
States
{
Spawn:
GWAN A -1;
Stop;
Ready:
GWND A 1 A_WeaponReady;
Loop;
Deselect:
GWND A 1 A_Lower;
Loop;
Select:
GWND A 1 A_Raise;
Loop;
Fire:
GWND B 3;
GWND C 5 A_FireGoldWandPL1;
GWND D 3;
GWND D 0 A_ReFire;
Goto Ready;
}
}
class GoldWandPowered : GoldWand
{
Default
{
+WEAPON.POWERED_UP
Weapon.AmmoGive 0;
Weapon.SisterWeapon "GoldWand";
Obituary "$OB_MPPGOLDWAND";
Tag "$TAG_GOLDWANDP";
}
action native void A_FireGoldWandPL2 ();
States
{
Fire:
GWND B 3;
GWND C 4 A_FireGoldWandPL2;
GWND D 3;
GWND D 0 A_ReFire;
Goto Ready;
}
}
// Gold wand FX1 ------------------------------------------------------------
class GoldWandFX1 : Actor
{
Default
{
Radius 10;
Height 6;
Speed 22;
Damage 2;
Projectile;
RenderStyle "Add";
DeathSound "weapons/wandhit";
Obituary "$OB_MPPGOLDWAND";
}
States
{
Spawn:
FX01 AB 6 BRIGHT;
Loop;
Death:
FX01 EFGH 3 BRIGHT;
Stop;
}
}
// Gold wand FX2 ------------------------------------------------------------
class GoldWandFX2 : GoldWandFX1
{
Default
{
Speed 18;
Damage 1;
DeathSound "";
}
States
{
Spawn:
FX01 CD 6 BRIGHT;
Loop;
}
}
// Gold wand puff 1 ---------------------------------------------------------
class GoldWandPuff1 : Actor
{
Default
{
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
RenderStyle "Add";
}
States
{
Spawn:
PUF2 ABCDE 3 BRIGHT;
Stop;
}
}
// Gold wand puff 2 ---------------------------------------------------------
class GoldWandPuff2 : GoldWandFX1
{
Default
{
Skip_Super;
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
}
States
{
Spawn:
Goto Super::Death;
}
}
// Crossbow -----------------------------------------------------------------
class Crossbow : HereticWeapon

View File

@ -0,0 +1,147 @@
// Staff --------------------------------------------------------------------
class Staff : HereticWeapon
{
Default
{
Weapon.SelectionOrder 3800;
+THRUGHOST
+WEAPON.WIMPY_WEAPON
+WEAPON.MELEEWEAPON
Weapon.sisterweapon "StaffPowered";
Obituary "$OB_MPSTAFF";
Tag "$TAG_STAFF";
}
States
{
Ready:
STFF A 1 A_WeaponReady;
Loop;
Deselect:
STFF A 1 A_Lower;
Loop;
Select:
STFF A 1 A_Raise;
Loop;
Fire:
STFF B 6;
STFF C 8 A_StaffAttack(random[StaffAttack](5, 20), "StaffPuff");
STFF B 8 A_ReFire;
Goto Ready;
}
//----------------------------------------------------------------------------
//
// PROC A_StaffAttackPL1
//
//----------------------------------------------------------------------------
action void A_StaffAttack (int damage, class<Actor> puff)
{
FTranslatedLineTarget t;
if (player == null)
{
return;
}
Weapon weapon = player.ReadyWeapon;
if (weapon != null)
{
if (!weapon.DepleteAmmo (weapon.bAltFire))
return;
}
double ang = angle + Random2[StaffAtk]() * (5.625 / 256);
double slope = AimLineAttack (ang, MELEERANGE);
LineAttack (ang, MELEERANGE, slope, damage, 'Melee', puff, true, t);
if (t.linetarget)
{
//S_StartSound(player.mo, sfx_stfhit);
// turn to face target
angle = t.angleFromSource;
}
}
}
class StaffPowered : Staff
{
Default
{
Weapon.sisterweapon "Staff";
Weapon.ReadySound "weapons/staffcrackle";
+WEAPON.POWERED_UP
+WEAPON.READYSNDHALF
+WEAPON.STAFF2_KICKBACK
Obituary "$OB_MPPSTAFF";
Tag "$TAG_STAFFP";
}
States
{
Ready:
STFF DEF 4 A_WeaponReady;
Loop;
Deselect:
STFF D 1 A_Lower;
Loop;
Select:
STFF D 1 A_Raise;
Loop;
Fire:
STFF G 6;
STFF H 8 A_StaffAttack(random[StaffAttack](18, 81), "StaffPuff2");
STFF G 8 A_ReFire;
Goto Ready;
}
}
// Staff puff ---------------------------------------------------------------
class StaffPuff : Actor
{
Default
{
RenderStyle "Translucent";
Alpha 0.4;
VSpeed 1;
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
AttackSound "weapons/staffhit";
}
States
{
Spawn:
PUF3 A 4 BRIGHT;
PUF3 BCD 4;
Stop;
}
}
// Staff puff 2 -------------------------------------------------------------
class StaffPuff2 : Actor
{
Default
{
RenderStyle "Add";
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
AttackSound "weapons/staffpowerhit";
}
States
{
Spawn:
PUF4 ABCDEF 4 BRIGHT;
Stop;
}
}

View File

@ -0,0 +1,217 @@
// Gold wand ----------------------------------------------------------------
class GoldWand : HereticWeapon
{
Default
{
+BLOODSPLATTER
Weapon.SelectionOrder 2000;
Weapon.AmmoGive 25;
Weapon.AmmoUse 1;
Weapon.AmmoType "GoldWandAmmo";
Weapon.SisterWeapon "GoldWandPowered";
Weapon.YAdjust 5;
Inventory.PickupMessage "$TXT_WPNGOLDWAND";
Obituary "$OB_MPGOLDWAND";
Tag "$TAG_GOLDWAND";
}
States
{
Spawn:
GWAN A -1;
Stop;
Ready:
GWND A 1 A_WeaponReady;
Loop;
Deselect:
GWND A 1 A_Lower;
Loop;
Select:
GWND A 1 A_Raise;
Loop;
Fire:
GWND B 3;
GWND C 5 A_FireGoldWandPL1;
GWND D 3;
GWND D 0 A_ReFire;
Goto Ready;
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL1
//
//----------------------------------------------------------------------------
action void A_FireGoldWandPL1 ()
{
if (player == null)
{
return;
}
Weapon weapon = player.ReadyWeapon;
if (weapon != null)
{
if (!weapon.DepleteAmmo (weapon.bAltFire))
return;
}
double pitch = BulletSlope();
int damage = 7 + random[FireGoldWand]() & 7;
double ang = angle;
if (player.refire)
{
ang += Random2[FireGoldWand]() * (5.625 / 256);
}
LineAttack(ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "GoldWandPuff1");
A_PlaySound("weapons/wandhit", CHAN_WEAPON);
}
}
class GoldWandPowered : GoldWand
{
Default
{
+WEAPON.POWERED_UP
Weapon.AmmoGive 0;
Weapon.SisterWeapon "GoldWand";
Obituary "$OB_MPPGOLDWAND";
Tag "$TAG_GOLDWANDP";
}
States
{
Fire:
GWND B 3;
GWND C 4 A_FireGoldWandPL2;
GWND D 3;
GWND D 0 A_ReFire;
Goto Ready;
}
//----------------------------------------------------------------------------
//
// PROC A_FireGoldWandPL2
//
//----------------------------------------------------------------------------
action void A_FireGoldWandPL2 ()
{
if (player == null)
{
return;
}
Weapon weapon = player.ReadyWeapon;
if (weapon != null)
{
if (!weapon.DepleteAmmo (weapon.bAltFire))
return;
}
double pitch = BulletSlope();
double vz = -GetDefaultByType("GoldWandFX2").Speed * clamp(tan(pitch), -5, 5);
SpawnMissileAngle("GoldWandFX2", angle - (45. / 8), vz);
SpawnMissileAngle("GoldWandFX2", angle + (45. / 8), vz);
double ang = angle - (45. / 8);
for(int i = 0; i < 5; i++)
{
int damage = random[FireGoldWand](1, 8);
LineAttack (ang, PLAYERMISSILERANGE, pitch, damage, 'Hitscan', "GoldWandPuff2");
ang += ((45. / 8) * 2) / 4;
}
A_PlaySound("weapons/wandhit", CHAN_WEAPON);
}
}
// Gold wand FX1 ------------------------------------------------------------
class GoldWandFX1 : Actor
{
Default
{
Radius 10;
Height 6;
Speed 22;
Damage 2;
Projectile;
RenderStyle "Add";
DeathSound "weapons/wandhit";
Obituary "$OB_MPPGOLDWAND";
}
States
{
Spawn:
FX01 AB 6 BRIGHT;
Loop;
Death:
FX01 EFGH 3 BRIGHT;
Stop;
}
}
// Gold wand FX2 ------------------------------------------------------------
class GoldWandFX2 : GoldWandFX1
{
Default
{
Speed 18;
Damage 1;
DeathSound "";
}
States
{
Spawn:
FX01 CD 6 BRIGHT;
Loop;
}
}
// Gold wand puff 1 ---------------------------------------------------------
class GoldWandPuff1 : Actor
{
Default
{
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
RenderStyle "Add";
}
States
{
Spawn:
PUF2 ABCDE 3 BRIGHT;
Stop;
}
}
// Gold wand puff 2 ---------------------------------------------------------
class GoldWandPuff2 : GoldWandFX1
{
Default
{
Skip_Super;
+NOBLOCKMAP
+NOGRAVITY
+PUFFONACTORS
}
States
{
Spawn:
Goto Super::Death;
}
}