mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 13:01:47 +00:00
- scriptified hexenspecialdecs.
- made '->' a single token. Although ZScript does not use it, the parser tends to get confused and fatally chokes on leftover arrows so this ensures more robust error handling.
This commit is contained in:
parent
de6969997a
commit
5ce5466e18
11 changed files with 284 additions and 500 deletions
|
@ -859,9 +859,7 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
${OTHER_SYSTEM_SOURCES}
|
||||
sc_man_scanner.h
|
||||
sc_man_scanner.re
|
||||
g_hexen/a_flies.cpp
|
||||
g_hexen/a_heresiarch.cpp
|
||||
g_hexen/a_hexenspecialdecs.cpp
|
||||
g_hexen/a_magecone.cpp
|
||||
g_hexen/a_magelightning.cpp
|
||||
g_hexen/a_magestaff.cpp
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
static FRandom pr_fly("GetOffMeFly");
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// FindCorpse
|
||||
//
|
||||
// Finds a corpse to buzz around. We can't use a blockmap check because
|
||||
// corpses generally aren't linked into the blockmap.
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
static AActor *FindCorpse(AActor *fly, sector_t *sec, int recurselimit)
|
||||
{
|
||||
AActor *fallback = NULL;
|
||||
sec->validcount = validcount;
|
||||
|
||||
// Search the current sector
|
||||
for (AActor *check = sec->thinglist; check != NULL; check = check->snext)
|
||||
{
|
||||
if (check == fly)
|
||||
continue;
|
||||
if (!(check->flags & MF_CORPSE))
|
||||
continue;
|
||||
if (!P_CheckSight(fly, check))
|
||||
continue;
|
||||
fallback = check;
|
||||
if (pr_fly(2)) // 50% chance to try to pick a different corpse
|
||||
continue;
|
||||
return check;
|
||||
}
|
||||
if (--recurselimit <= 0 || (fallback != NULL && pr_fly(2)))
|
||||
{
|
||||
return fallback;
|
||||
}
|
||||
// Try neighboring sectors
|
||||
for (int i = 0; i < sec->linecount; ++i)
|
||||
{
|
||||
line_t *line = sec->lines[i];
|
||||
sector_t *sec2 = (line->frontsector == sec) ? line->backsector : line->frontsector;
|
||||
if (sec2 != NULL && sec2->validcount != validcount)
|
||||
{
|
||||
AActor *neighbor = FindCorpse(fly, sec2, recurselimit);
|
||||
if (neighbor != NULL)
|
||||
{
|
||||
return neighbor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return fallback;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FlySearch)
|
||||
{
|
||||
// The version from the retail beta is not so great for general use:
|
||||
// 1. Pick one of the first fifty thinkers at random.
|
||||
// 2. Starting from that thinker, find one that is an actor, not itself,
|
||||
// and within sight. Give up after 100 sequential thinkers.
|
||||
// It's effectively useless if there are more than 150 thinkers on a map.
|
||||
//
|
||||
// So search the sectors instead. We can't potentially find something all
|
||||
// the way on the other side of the map and we can't find invisible corpses,
|
||||
// but at least we aren't crippled on maps with lots of stuff going on.
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
validcount++;
|
||||
AActor *other = FindCorpse(self, self->Sector, 5);
|
||||
if (other != NULL)
|
||||
{
|
||||
self->target = other;
|
||||
self->SetState(self->FindState("Buzz"));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_FlyBuzz)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *targ = self->target;
|
||||
|
||||
if (targ == NULL || !(targ->flags & MF_CORPSE) || pr_fly() < 5)
|
||||
{
|
||||
self->SetIdle();
|
||||
return 0;
|
||||
}
|
||||
|
||||
self->Angles.Yaw = self->AngleTo(targ);
|
||||
self->args[0]++;
|
||||
if (!P_TryMove(self, self->Pos().XY() + self->Angles.Yaw.ToVector(6), true))
|
||||
{
|
||||
self->SetIdle(true);
|
||||
return 0;
|
||||
}
|
||||
if (self->args[0] & 2)
|
||||
{
|
||||
self->Vel.X += (pr_fly() - 128) / 512.;
|
||||
self->Vel.Y += (pr_fly() - 128) / 512.;
|
||||
}
|
||||
int zrand = pr_fly();
|
||||
if (targ->Z() + 5. < self->Z() && zrand > 150)
|
||||
{
|
||||
zrand = -zrand;
|
||||
}
|
||||
self->Vel.Z = zrand / 512.;
|
||||
if (pr_fly() < 40)
|
||||
{
|
||||
S_Sound(self, CHAN_VOICE, self->ActiveSound, 0.5f, ATTN_STATIC);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -24,9 +24,7 @@
|
|||
#include "a_pickups.h"
|
||||
|
||||
// Include all the Hexen stuff here to reduce compile time
|
||||
#include "a_flies.cpp"
|
||||
#include "a_heresiarch.cpp"
|
||||
#include "a_hexenspecialdecs.cpp"
|
||||
#include "a_magecone.cpp"
|
||||
#include "a_magelightning.cpp"
|
||||
#include "a_magestaff.cpp"
|
||||
|
|
|
@ -1,365 +0,0 @@
|
|||
/*
|
||||
** Decorations that do special things
|
||||
*/
|
||||
|
||||
/*
|
||||
#include "actor.h"
|
||||
#include "info.h"
|
||||
#include "a_action.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_local.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "a_hexenglobal.h"
|
||||
#include "vm.h"
|
||||
#include "g_level.h"
|
||||
#include "doomstat.h"
|
||||
*/
|
||||
|
||||
static FRandom pr_pottery ("PotteryExplode");
|
||||
static FRandom pr_bit ("PotteryChooseBit");
|
||||
static FRandom pr_drip ("CorpseBloodDrip");
|
||||
static FRandom pr_foo ("CorpseExplode");
|
||||
static FRandom pr_leaf ("LeafSpawn");
|
||||
static FRandom pr_leafthrust ("LeafThrust");
|
||||
static FRandom pr_leafcheck ("LeafCheck");
|
||||
static FRandom pr_shroom ("PoisonShroom");
|
||||
static FRandom pr_soaexplode ("SoAExplode");
|
||||
|
||||
// Pottery1 ------------------------------------------------------------------
|
||||
|
||||
void A_PotteryExplode (AActor *);
|
||||
void A_PotteryChooseBit (AActor *);
|
||||
void A_PotteryCheck (AActor *);
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryExplode
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_PotteryExplode)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *mo = NULL;
|
||||
int i;
|
||||
|
||||
for(i = (pr_pottery()&3)+3; i; i--)
|
||||
{
|
||||
mo = Spawn ("PotteryBit", self->Pos(), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->SetState (mo->SpawnState + (pr_pottery()%5));
|
||||
mo->Vel.X = pr_pottery.Random2() / 64.;
|
||||
mo->Vel.Y = pr_pottery.Random2() / 64.;
|
||||
mo->Vel.Z = ((pr_pottery() & 7) + 5) * 0.75;
|
||||
}
|
||||
}
|
||||
S_Sound (mo, CHAN_BODY, "PotteryExplode", 1, ATTN_NORM);
|
||||
// Spawn an item?
|
||||
PClassActor *type = P_GetSpawnableType(self->args[0]);
|
||||
if (type != NULL)
|
||||
{
|
||||
if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|
||||
|| !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER))
|
||||
{ // Only spawn monsters if not -nomonsters
|
||||
Spawn (type, self->Pos(), ALLOW_REPLACE);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryChooseBit
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_PotteryChooseBit)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->SetState (self->FindState(NAME_Death) + 1 + 2*(pr_bit()%5));
|
||||
self->tics = 256+(pr_bit()<<1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryCheck
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_PotteryCheck)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
AActor *pmo = players[i].mo;
|
||||
if (P_CheckSight (self, pmo) && (absangle(pmo->AngleTo(self), pmo->Angles.Yaw) <= 45))
|
||||
{ // Previous state (pottery bit waiting state)
|
||||
self->SetState (self->state - 1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lynched corpse (no heart) ------------------------------------------------
|
||||
|
||||
class AZCorpseLynchedNoHeart : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AZCorpseLynchedNoHeart, AActor)
|
||||
public:
|
||||
void PostBeginPlay ();
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AZCorpseLynchedNoHeart, false, false)
|
||||
|
||||
void AZCorpseLynchedNoHeart::PostBeginPlay ()
|
||||
{
|
||||
Super::PostBeginPlay ();
|
||||
Spawn ("BloodPool", PosAtZ(floorz), ALLOW_REPLACE);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_CorpseBloodDrip
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CorpseBloodDrip)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (pr_drip() <= 128)
|
||||
{
|
||||
Spawn ("CorpseBloodDrip", self->PosPlusZ(self->Height / 2), ALLOW_REPLACE);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_CorpseExplode
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_CorpseExplode)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *mo;
|
||||
int i;
|
||||
|
||||
for (i = (pr_foo()&3)+3; i; i--)
|
||||
{
|
||||
mo = Spawn ("CorpseBit", self->Pos(), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->SetState (mo->SpawnState + (pr_foo()%3));
|
||||
mo->Vel.X = pr_foo.Random2() / 64.;
|
||||
mo->Vel.Y = pr_foo.Random2() / 64.;
|
||||
mo->Vel.Z = ((pr_foo() & 7) + 5) * 0.75;
|
||||
}
|
||||
}
|
||||
// Spawn a skull
|
||||
mo = Spawn ("CorpseBit", self->Pos(), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->SetState (mo->SpawnState + 3);
|
||||
mo->Vel.X = pr_foo.Random2() / 64.;
|
||||
mo->Vel.Y = pr_foo.Random2() / 64.;
|
||||
mo->Vel.Z = ((pr_foo() & 7) + 5) * 0.75;
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_IDLE);
|
||||
self->Destroy ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafSpawn
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LeafSpawn)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *mo;
|
||||
int i;
|
||||
|
||||
for (i = (pr_leaf()&3)+1; i; i--)
|
||||
{
|
||||
double xo = pr_leaf.Random2() / 4.;
|
||||
double yo = pr_leaf.Random2() / 4.;
|
||||
double zo = pr_leaf() / 4.;
|
||||
mo = Spawn (pr_leaf()&1 ? PClass::FindActor ("Leaf1") : PClass::FindActor ("Leaf2"),
|
||||
self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
|
||||
if (mo)
|
||||
{
|
||||
mo->Thrust(pr_leaf() / 128. + 3);
|
||||
mo->target = self;
|
||||
mo->special1 = 0;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafThrust
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LeafThrust)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
if (pr_leafthrust() <= 96)
|
||||
{
|
||||
self->Vel.Z += pr_leafthrust() / 128. + 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafCheck
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_LeafCheck)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->special1++;
|
||||
if (self->special1 >= 20)
|
||||
{
|
||||
self->SetState (NULL);
|
||||
return 0;
|
||||
}
|
||||
DAngle ang = self->target ? self->target->Angles.Yaw : self->Angles.Yaw;
|
||||
if (pr_leafcheck() > 64)
|
||||
{
|
||||
if (self->Vel.X == 0 && self->Vel.Y == 0)
|
||||
{
|
||||
self->Thrust(ang, pr_leafcheck() / 128. + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
self->SetState (self->SpawnState + 7);
|
||||
self->Vel.Z = pr_leafcheck() / 128. + 1;
|
||||
self->Thrust(ang, pr_leafcheck() / 128. + 2);
|
||||
self->flags |= MF_MISSILE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SoAExplode - Suit of Armor Explode
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_SoAExplode)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
AActor *mo;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
{
|
||||
double xo = (pr_soaexplode() - 128) / 16.;
|
||||
double yo = (pr_soaexplode() - 128) / 16.;
|
||||
double zo = pr_soaexplode()*self->Height / 256.;
|
||||
mo = Spawn ("ZArmorChunk", self->Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo->SetState (mo->SpawnState + i);
|
||||
mo->Vel.X = pr_soaexplode.Random2() / 64.;
|
||||
mo->Vel.Y = pr_soaexplode.Random2() / 64.;
|
||||
mo->Vel.Z = (pr_soaexplode() & 7) + 5;
|
||||
}
|
||||
}
|
||||
// Spawn an item?
|
||||
PClassActor *type = P_GetSpawnableType(self->args[0]);
|
||||
if (type != NULL)
|
||||
{
|
||||
if (!((level.flags2 & LEVEL2_NOMONSTERS) || (dmflags & DF_NO_MONSTERS))
|
||||
|| !(GetDefaultByType (type)->flags3 & MF3_ISMONSTER))
|
||||
{ // Only spawn monsters if not -nomonsters
|
||||
Spawn (type, self->Pos(), ALLOW_REPLACE);
|
||||
}
|
||||
}
|
||||
S_Sound (self, CHAN_BODY, self->DeathSound, 1, ATTN_NORM);
|
||||
self->Destroy ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Bell ---------------------------------------------------------------------
|
||||
|
||||
class AZBell : public AActor
|
||||
{
|
||||
DECLARE_CLASS (AZBell, AActor)
|
||||
public:
|
||||
void Activate (AActor *activator);
|
||||
};
|
||||
|
||||
IMPLEMENT_CLASS(AZBell, false, false)
|
||||
|
||||
void AZBell::Activate (AActor *activator)
|
||||
{
|
||||
if (health > 0)
|
||||
{
|
||||
P_DamageMobj (this, activator, activator, 10, NAME_Melee, DMG_THRUSTLESS); // 'ring' the bell
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_BellReset1
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BellReset1)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->flags |= MF_NOGRAVITY;
|
||||
self->Height *= 4;
|
||||
if (self->special)
|
||||
{ // Initiate death action
|
||||
P_ExecuteSpecial(self->special, NULL, NULL, false, self->args[0],
|
||||
self->args[1], self->args[2], self->args[3], self->args[4]);
|
||||
self->special = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_BellReset2
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, A_BellReset2)
|
||||
{
|
||||
PARAM_SELF_PROLOGUE(AActor);
|
||||
|
||||
self->flags |= MF_SHOOTABLE;
|
||||
self->flags &= ~MF_CORPSE;
|
||||
self->flags6 &= ~MF6_KILLED;
|
||||
self->health = 5;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1889,6 +1889,7 @@ DEFINE_FIELD_BIT(FLevelLocals, flags2, missilesactivateimpact, LEVEL2_MISSILESAC
|
|||
DEFINE_FIELD_BIT(FLevelLocals, flags2, monsterfallingdamage, LEVEL2_MONSTERFALLINGDAMAGE)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, checkswitchrange, LEVEL2_CHECKSWITCHRANGE)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, polygrind, LEVEL2_POLYGRIND)
|
||||
DEFINE_FIELD_BIT(FLevelLocals, flags2, nomonsters, LEVEL2_NOMONSTERS)
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -520,6 +520,13 @@ PClassActor *P_GetSpawnableType(int spawnnum)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(AActor, GetSpawnableType)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(num);
|
||||
ACTION_RETURN_OBJECT(P_GetSpawnableType(num));
|
||||
}
|
||||
|
||||
struct MapinfoSpawnItem
|
||||
{
|
||||
FName classname; // DECORATE is read after MAPINFO so we do not have the actual classes available here yet.
|
||||
|
|
|
@ -162,13 +162,11 @@ std2:
|
|||
'private' { RET(TK_Private); }
|
||||
'dot' { RET(TK_Dot); }
|
||||
'cross' { RET(TK_Cross); }
|
||||
'ignores' { RET(TK_Ignores); }
|
||||
'localized' { RET(TK_Localized); }
|
||||
'latent' { RET(TK_Latent); }
|
||||
'singular' { RET(TK_Singular); }
|
||||
'config' { RET(TK_Config); }
|
||||
'coerce' { RET(TK_Coerce); }
|
||||
'iterator' { RET(TK_Iterator); }
|
||||
'optional' { RET(TK_Optional); }
|
||||
'export' { RET(TK_Export); }
|
||||
'virtual' { RET(TK_Virtual); }
|
||||
|
@ -240,6 +238,7 @@ std2:
|
|||
"<>=" { RET(TK_LtGtEq); }
|
||||
"**" { RET(TK_MulMul); }
|
||||
"::" { RET(TK_ColonColon); }
|
||||
"->" { RET(TK_Arrow); }
|
||||
";" { StateOptions = false; RET(';'); }
|
||||
"{" { StateOptions = false; RET('{'); }
|
||||
"}" { RET('}'); }
|
||||
|
|
|
@ -33,6 +33,7 @@ xx(TK_Neq, "'!='")
|
|||
xx(TK_ApproxEq, "'~=='")
|
||||
xx(TK_LtGtEq, "'<>='")
|
||||
xx(TK_MulMul, "'**'")
|
||||
xx(TK_Arrow, "'->'")
|
||||
xx(TK_Action, "'action'")
|
||||
xx(TK_Break, "'break'")
|
||||
xx(TK_Case, "'case'")
|
||||
|
|
|
@ -270,6 +270,7 @@ class Actor : Thinker native
|
|||
|
||||
|
||||
native static double GetDefaultSpeed(class<Actor> type);
|
||||
native static class<Actor> GetSpawnableType(int spawnnum);
|
||||
native void RemoveFromHash();
|
||||
native string GetTag(string defstr = "");
|
||||
native double GetBobOffset(double frac = 0);
|
||||
|
|
|
@ -92,6 +92,7 @@ struct LevelLocals native
|
|||
native bool monsterfallingdamage;
|
||||
native bool checkswitchrange;
|
||||
native bool polygrind;
|
||||
native bool nomonsters;
|
||||
// level_info_t *info cannot be done yet.
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,6 @@ class Pottery1 : Actor
|
|||
+NOICEDEATH
|
||||
}
|
||||
|
||||
native void A_PotteryExplode();
|
||||
|
||||
States
|
||||
{
|
||||
|
@ -106,6 +105,40 @@ class Pottery1 : Actor
|
|||
POT1 A 0 A_PotteryExplode;
|
||||
Stop;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryExplode
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_PotteryExplode()
|
||||
{
|
||||
Actor mo = null;
|
||||
int i;
|
||||
|
||||
for(i = (random[Pottery]()&3)+3; i; i--)
|
||||
{
|
||||
mo = Spawn ("PotteryBit", Pos, ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo.SetState (mo.SpawnState + (random[Pottery]()%5));
|
||||
mo.Vel.X = random2[Pottery]() / 64.;
|
||||
mo.Vel.Y = random2[Pottery]() / 64.;
|
||||
mo.Vel.Z = ((random[Pottery]() & 7) + 5) * 0.75;
|
||||
}
|
||||
}
|
||||
mo.A_PlaySound ("PotteryExplode", CHAN_BODY);
|
||||
// Spawn an item?
|
||||
Class<Actor> type = GetSpawnableType(args[0]);
|
||||
if (type != null)
|
||||
{
|
||||
if (!(level.nomonsters || sv_nomonsters) || !(GetDefaultByType (type).bIsMonster))
|
||||
{ // Only spawn monsters if not -nomonsters
|
||||
Spawn (type, Pos, ALLOW_REPLACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pottery2 -----------------------------------------------------------------
|
||||
|
@ -144,6 +177,8 @@ class Pottery3 : Pottery1
|
|||
|
||||
class PotteryBit : Actor
|
||||
{
|
||||
State LoopState;
|
||||
|
||||
Default
|
||||
{
|
||||
Radius 5;
|
||||
|
@ -153,9 +188,6 @@ class PotteryBit : Actor
|
|||
+NOICEDEATH
|
||||
}
|
||||
|
||||
native void A_PotteryChooseBit();
|
||||
native void A_PotteryCheck();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
|
@ -185,6 +217,42 @@ class PotteryBit : Actor
|
|||
PBIT J 1 A_PotteryCheck;
|
||||
Stop;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryChooseBit
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_PotteryChooseBit()
|
||||
{
|
||||
static const statelabel bits[] = { "Pottery1", "Pottery2", "Pottery3", "Pottery4", "Pottery5" };
|
||||
LoopState = FindState(bits[random[PotteryBit]() % 5]); // Save the state for jumping back to.
|
||||
SetState (LoopState);
|
||||
tics = 256 + (random[PotteryBit]() << 1);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_PotteryCheck
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_PotteryCheck()
|
||||
{
|
||||
for(int i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
Actor pmo = players[i].mo;
|
||||
if (CheckSight (pmo) && (absangle(pmo.AngleTo(self), pmo.Angle) <= 45))
|
||||
{ // jump back to previpusly set state.
|
||||
SetState (LoopState);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -203,7 +271,7 @@ class BloodPool : Actor
|
|||
|
||||
// Lynched corpse (no heart) ------------------------------------------------
|
||||
|
||||
class ZCorpseLynchedNoHeart : Actor native
|
||||
class ZCorpseLynchedNoHeart : Actor
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -212,14 +280,32 @@ class ZCorpseLynchedNoHeart : Actor native
|
|||
+SOLID +SPAWNCEILING +NOGRAVITY
|
||||
}
|
||||
|
||||
native void A_CorpseBloodDrip();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
CPS5 A 140 A_CorpseBloodDrip;
|
||||
Loop;
|
||||
}
|
||||
|
||||
override void PostBeginPlay ()
|
||||
{
|
||||
Super.PostBeginPlay ();
|
||||
Spawn ("BloodPool", (pos.xy, floorz), ALLOW_REPLACE);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_CorpseBloodDrip
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_CorpseBloodDrip()
|
||||
{
|
||||
if (random[CorpseDrip]() <= 128)
|
||||
{
|
||||
Spawn ("CorpseBloodDrip", pos + (0, 0, Height / 2), ALLOW_REPLACE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -289,8 +375,6 @@ class ZCorpseSitting : Actor
|
|||
DeathSound "FireDemonDeath";
|
||||
}
|
||||
|
||||
native void A_CorpseExplode();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
|
@ -300,6 +384,40 @@ class ZCorpseSitting : Actor
|
|||
CPS6 A 1 A_CorpseExplode;
|
||||
Stop;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_CorpseExplode
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_CorpseExplode()
|
||||
{
|
||||
Actor mo;
|
||||
|
||||
for (int i = (random[CorpseExplode]() & 3) + 3; i; i--)
|
||||
{
|
||||
mo = Spawn ("CorpseBit", Pos, ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo.SetState (mo.SpawnState + (random[CorpseExplode]() % 3));
|
||||
mo.Vel.X = random2[CorpseExplode]() / 64.;
|
||||
mo.Vel.Y = random2[CorpseExplode]() / 64.;
|
||||
mo.Vel.Z = ((random[CorpseExplode]() & 7) + 5) * 0.75;
|
||||
}
|
||||
}
|
||||
// Spawn a skull
|
||||
mo = Spawn ("CorpseBit", Pos, ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo.SetState (mo.SpawnState + 3);
|
||||
mo.Vel.X = random2[CorpseExplode]() / 64.;
|
||||
mo.Vel.Y = random2[CorpseExplode]() / 64.;
|
||||
mo.Vel.Z = ((random[CorpseExplode]() & 7) + 5) * 0.75;
|
||||
}
|
||||
A_PlaySound (DeathSound, CHAN_BODY);
|
||||
Destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -313,7 +431,6 @@ class LeafSpawner : Actor
|
|||
+INVISIBLE
|
||||
}
|
||||
|
||||
native void A_LeafSpawn();
|
||||
|
||||
States
|
||||
{
|
||||
|
@ -321,6 +438,32 @@ class LeafSpawner : Actor
|
|||
TNT1 A 20 A_LeafSpawn;
|
||||
Loop;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafSpawn
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_LeafSpawn()
|
||||
{
|
||||
static const class<Actor> leaves[] = { "Leaf1", "Leaf2" };
|
||||
|
||||
for (int i = (random[LeafSpawn]() & 3) + 1; i; i--)
|
||||
{
|
||||
double xo = random2[LeafSpawn]() / 4.;
|
||||
double yo = random2[LeafSpawn]() / 4.;
|
||||
double zo = random[LeafSpawn]() / 4.;
|
||||
Actor mo = Spawn (leaves[random[LeafSpawn]()&1], Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
|
||||
if (mo)
|
||||
{
|
||||
mo.Thrust(random[LeafSpawn]() / 128. + 3);
|
||||
mo.target = self;
|
||||
mo.special1 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -338,15 +481,13 @@ class Leaf1 : Actor
|
|||
+NOICEDEATH
|
||||
}
|
||||
|
||||
native void A_LeafThrust();
|
||||
native void A_LeafCheck();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
LEF1 ABC 4;
|
||||
LEF1 D 4 A_LeafThrust;
|
||||
LEF1 EFG 4;
|
||||
Looping:
|
||||
LEF1 H 4 A_LeafThrust;
|
||||
LEF1 I 4;
|
||||
LEF1 AB 4;
|
||||
|
@ -359,6 +500,49 @@ class Leaf1 : Actor
|
|||
LEF3 D 10 A_LeafCheck;
|
||||
Wait;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafThrust
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_LeafThrust()
|
||||
{
|
||||
if (random[LeafThrust]() <= 96)
|
||||
{
|
||||
Vel.Z += random[LeafThrust]() / 128. + 1;
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
//
|
||||
// A_LeafCheck
|
||||
//
|
||||
//============================================================================
|
||||
|
||||
void A_LeafCheck()
|
||||
{
|
||||
special1++;
|
||||
if (special1 >= 20)
|
||||
{
|
||||
Destroy();
|
||||
return;
|
||||
}
|
||||
double ang = target ? target.angle : angle;
|
||||
if (random[LeafCheck]() > 64)
|
||||
{
|
||||
if (Vel.X == 0 && Vel.Y == 0)
|
||||
{
|
||||
Thrust(random[LeafCheck]() / 128. + 1, ang);
|
||||
}
|
||||
return;
|
||||
}
|
||||
SetStateLabel ("Looping");
|
||||
Vel.Z = random[LeafCheck]() / 128. + 1;
|
||||
Thrust(random[LeafCheck]() / 128. + 2, ang);
|
||||
bMissile = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -556,8 +740,6 @@ class ZSuitOfArmor : Actor
|
|||
DeathSound "SuitofArmorBreak";
|
||||
}
|
||||
|
||||
native void A_SoAExplode();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
|
@ -567,6 +749,41 @@ class ZSuitOfArmor : Actor
|
|||
ZSUI A 1 A_SoAExplode;
|
||||
Stop;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_SoAExplode - Suit of Armor Explode
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void A_SoAExplode()
|
||||
{
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
double xo = (random[SoAExplode]() - 128) / 16.;
|
||||
double yo = (random[SoAExplode]() - 128) / 16.;
|
||||
double zo = random[SoAExplode]() * Height / 256.;
|
||||
Actor mo = Spawn ("ZArmorChunk", Vec3Offset(xo, yo, zo), ALLOW_REPLACE);
|
||||
if (mo)
|
||||
{
|
||||
mo.SetState (mo.SpawnState + i);
|
||||
mo.Vel.X = random2[SoAExplode]() / 64.;
|
||||
mo.Vel.Y = random2[SoAExplode]() / 64.;
|
||||
mo.Vel.Z = (random[SoAExplode]() & 7) + 5;
|
||||
}
|
||||
}
|
||||
// Spawn an item?
|
||||
Class<Actor> type = GetSpawnableType(args[0]);
|
||||
if (type != null)
|
||||
{
|
||||
if (!(level.nomonsters || sv_nomonsters) || !(GetDefaultByType (type).bIsMonster))
|
||||
{ // Only spawn monsters if not -nomonsters
|
||||
Spawn (type, Pos, ALLOW_REPLACE);
|
||||
}
|
||||
}
|
||||
A_PlaySound (DeathSound, CHAN_BODY);
|
||||
Destroy ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -608,7 +825,7 @@ class ZArmorChunk : Actor
|
|||
|
||||
// Bell ---------------------------------------------------------------------
|
||||
|
||||
class ZBell : Actor native
|
||||
class ZBell : Actor
|
||||
{
|
||||
Default
|
||||
{
|
||||
|
@ -621,9 +838,6 @@ class ZBell : Actor native
|
|||
DeathSound "BellRing";
|
||||
}
|
||||
|
||||
native void A_BellReset1();
|
||||
native void A_BellReset2();
|
||||
|
||||
States
|
||||
{
|
||||
Spawn:
|
||||
|
@ -665,6 +879,45 @@ class ZBell : Actor native
|
|||
BBLL A 1 A_BellReset2;
|
||||
Goto Spawn;
|
||||
}
|
||||
|
||||
override void Activate (Actor activator)
|
||||
{
|
||||
if (health > 0) A_Die();
|
||||
{
|
||||
DamageMobj (activator, activator, 10, 'Melee', DMG_THRUSTLESS); // 'ring' the bell
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_BellReset1
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void A_BellReset1()
|
||||
{
|
||||
bNoGravity = true;
|
||||
Height = Default.Height;
|
||||
if (special)
|
||||
{ // Initiate death action
|
||||
A_CallSpecial(special, args[0], args[1], args[2], args[3], args[4]);
|
||||
special = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// A_BellReset2
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
void A_BellReset2()
|
||||
{
|
||||
bShootable = true;
|
||||
bCorpse = false;
|
||||
bKilled = false;
|
||||
health = 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue